From 624231601a0f5daea9b8809993ad3503beafce4f Mon Sep 17 00:00:00 2001
From: stephane Domas <stephane.domas@univ-fcomte.fr>
Date: Tue, 9 May 2017 22:33:37 +0200
Subject: [PATCH] source connection ok

---
 AbstractBlock.cpp       |   8 ++++
 AbstractBlock.h         |   2 +
 ConnectionItem.cpp      | 101 ++++++++++++++++++++++++++--------------
 ConnectionItem.h        |   3 +-
 Dispatcher.cpp          |  20 ++++----
 FunctionalBlock.cpp     |   5 ++
 FunctionalBlock.h       |   1 +
 FunctionalInterface.cpp |   7 ++-
 GroupBlock.cpp          |   4 ++
 GroupBlock.h            |   1 +
 GroupInterface.cpp      |   6 +++
 GroupItem.cpp           |  26 +++--------
 GroupScene.cpp          |  12 ++---
 GroupScene.h            |   2 +-
 InterfaceItem.cpp       |  55 +++++++++++-----------
 InterfaceItem.h         |   5 +-
 blast.creator.user      |   8 ++--
 17 files changed, 161 insertions(+), 105 deletions(-)

diff --git a/AbstractBlock.cpp b/AbstractBlock.cpp
index ba1c179..87c973c 100644
--- a/AbstractBlock.cpp
+++ b/AbstractBlock.cpp
@@ -44,6 +44,14 @@ bool AbstractBlock::isGroupBlock() {
   return false;
 }
 
+bool AbstractBlock::isTopGroupBlock() {  
+  return false;
+}
+
+bool AbstractBlock::isSourceBlock() {
+  return false;
+}
+
 void AbstractBlock::addParameter(BlockParameter *param) {
   params.append(param);
 }
diff --git a/AbstractBlock.h b/AbstractBlock.h
index 28e8b7a..a132bc8 100644
--- a/AbstractBlock.h
+++ b/AbstractBlock.h
@@ -43,6 +43,8 @@ public:
   virtual bool isReferenceBlock();
   virtual bool isFunctionalBlock();
   virtual bool isGroupBlock();
+  virtual bool isSourceBlock();
+  virtual bool isTopGroupBlock();
   bool isWBConfigurable();
 
   // others
diff --git a/ConnectionItem.cpp b/ConnectionItem.cpp
index 78a3651..c99d489 100644
--- a/ConnectionItem.cpp
+++ b/ConnectionItem.cpp
@@ -12,8 +12,7 @@
 ConnectionItem::ConnectionItem(InterfaceItem* _iface1,
                                InterfaceItem* _iface2,
                                Dispatcher* _dispatcher,
-                               Parameters* _params,
-                               QGraphicsItem *_parent) : QGraphicsItem(_parent) {
+                               Parameters* _params) : QGraphicsItem() {
 
 
   dispatcher = _dispatcher;
@@ -25,6 +24,8 @@ ConnectionItem::ConnectionItem(InterfaceItem* _iface1,
      case 1 : ref1 is group interface, and ref2 block interface of a block within the group
      case 2 : the opposite of case 1
      case 3 : ref1 and ref2 are block interface of blocks that are both within the same parent group.
+     case 4 : ref1 is source interface and ref2 interface of top group
+     case 5 : the opposite of case 4
    */
   if (ref1->getOwner() == ref2->getOwner()->getParent()) {
 
@@ -72,6 +73,14 @@ ConnectionItem::ConnectionItem(InterfaceItem* _iface1,
       fromInterfaceItem = _iface1;
     }
   }
+  else if ((ref1->getOwner()->isSourceBlock()) && (ref2->getOwner()->isTopGroupBlock())) {    
+    fromInterfaceItem = _iface1;    
+    toInterfaceItem = _iface2;
+  }
+  else if ((ref2->getOwner()->isSourceBlock()) && (ref1->getOwner()->isTopGroupBlock())) {    
+    fromInterfaceItem = _iface2;    
+    toInterfaceItem = _iface1;
+  }
   // adding this to interface items
   fromInterfaceItem->addConnectionItem(this);
   toInterfaceItem->addConnectionItem(this);
@@ -159,8 +168,30 @@ void ConnectionItem::setPath() {
   // signals to the scene that this connection is going to change of shape.
   prepareGeometryChange();
 
-  pointFrom = fromInterfaceItem->getEndPointInGroup();
-  pointTo = toInterfaceItem->getEndPointInGroup();
+  bool withinGroup = false;
+  /* NB: four cases
+     1: from group input iface to box input iface
+     2: from output box iface to group output iface
+     3: from output box iface to input box iface
+     4: from source output iface to input group iface
+   
+    For cases 1 & 2, the position of group iface is given by getStartPosition
+    For all other cases, the iface from and to position is given by getEndPosition
+   */
+  if ((fromInterfaceItem->getOwner()->isGroupItem()) && (toInterfaceItem->getOwner()->isBoxItem())) {
+    pointFrom = fromInterfaceItem->getStartPosition();
+    pointTo = toInterfaceItem->getEndPosition();
+    withinGroup = true;
+  }
+  else if ((toInterfaceItem->getOwner()->isGroupItem()) && (fromInterfaceItem->getOwner()->isBoxItem())) {
+    pointFrom = fromInterfaceItem->getEndPosition();
+    pointTo = toInterfaceItem->getStartPosition();
+    withinGroup = true;
+  }
+  else {
+    pointFrom = fromInterfaceItem->getEndPosition();
+    pointTo = toInterfaceItem->getEndPosition();
+  }
 
   int oriFrom, oriTo;
   oriFrom = fromInterfaceItem->getOrientation();
@@ -169,36 +200,38 @@ void ConnectionItem::setPath() {
 /* NB: if src or dest is onwed by a GroupItem the orientation
    must be changed as it is a block.
  */
-  if(fromInterfaceItem->owner->isGroupItem()){
-    switch(fromInterfaceItem->getOrientation()){
-    case Parameters::North :
-      oriFrom = Parameters::South;
-      break;
-    case Parameters::South :
-      oriFrom = Parameters::North;
-      break;
-    case Parameters::East :
-      oriFrom = Parameters::West;
-      break;
-    case Parameters::West :
-      oriFrom = Parameters::East;
-      break;
-    }
-  }
-  if(toInterfaceItem->owner->isGroupItem()){
-    switch(toInterfaceItem->getOrientation()){
-    case Parameters::North :
-      oriTo = Parameters::South;
-      break;
-    case Parameters::South :
-      oriTo = Parameters::North;
-      break;
-    case Parameters::East :
-      oriTo = Parameters::West;
-      break;
-    case Parameters::West :
-      oriTo = Parameters::East;
-      break;
+  if (withinGroup) {
+    if(fromInterfaceItem->owner->isGroupItem()){
+      switch(fromInterfaceItem->getOrientation()){
+      case Parameters::North :
+        oriFrom = Parameters::South;
+        break;
+      case Parameters::South :
+        oriFrom = Parameters::North;
+        break;
+      case Parameters::East :
+        oriFrom = Parameters::West;
+        break;
+      case Parameters::West :
+        oriFrom = Parameters::East;
+        break;
+      }
+    }
+    else if(toInterfaceItem->owner->isGroupItem()){
+      switch(toInterfaceItem->getOrientation()){
+      case Parameters::North :
+        oriTo = Parameters::South;
+        break;
+      case Parameters::South :
+        oriTo = Parameters::North;
+        break;
+      case Parameters::East :
+        oriTo = Parameters::West;
+        break;
+      case Parameters::West :
+        oriTo = Parameters::East;
+        break;
+      }
     }
   }
   double gap1 = 0.0;
diff --git a/ConnectionItem.h b/ConnectionItem.h
index c64839f..5548715 100644
--- a/ConnectionItem.h
+++ b/ConnectionItem.h
@@ -41,8 +41,7 @@ public:
   ConnectionItem(InterfaceItem* _iface1,
                  InterfaceItem* _iface2,
                  Dispatcher* _dispatcher,
-                 Parameters* _params,
-                 QGraphicsItem* _parent);
+                 Parameters* _params);
   ConnectionItem (const ConnectionItem & copy);
   ConnectionItem();
   ~ConnectionItem();
diff --git a/Dispatcher.cpp b/Dispatcher.cpp
index bbbb945..10880cc 100644
--- a/Dispatcher.cpp
+++ b/Dispatcher.cpp
@@ -82,7 +82,7 @@ void Dispatcher::closeCurrentProject() {
 }
 
 bool Dispatcher::createConnectionItem(InterfaceItem *iface1, InterfaceItem *iface2) {
-
+    
   ConnectedInterface* ref1 = iface1->refInter;
   ConnectedInterface* ref2 = iface2->refInter;
   // connect both interface
@@ -90,13 +90,17 @@ bool Dispatcher::createConnectionItem(InterfaceItem *iface1, InterfaceItem *ifac
   bool ok1 = false;
   bool ok2 = false;
 
-  if (ref1->canConnectTo(ref2)) {
-    ok1 = ref1->connectTo(ref2);
-    ok1 = ok1 & ref2->connectFrom(ref1);
-  }
-  if (ref2->canConnectTo(ref1)) {
-    ok2 = ref2->connectTo(ref1);
-    ok2 = ok2 & ref1->connectFrom(ref2);
+  // test the ref1->ref2 connection
+  if ((ref1->canConnectTo(ref2)) && (ref2->canConnectFrom(ref1))) {
+    ref1->connectTo(ref2);
+    ref2->connectFrom(ref1);
+    ok1 = true;
+  }
+  // if the frist one did not work, test ref2->ref1
+  if ((ok1 == false) && (ref2->canConnectTo(ref1)) && (ref1->canConnectFrom(ref2))) {  
+    ref2->connectTo(ref1);
+    ref1->connectFrom(ref2);
+    ok2 = true;
   }
   if ((ok1 == true) || (ok2 == true)) {
 
diff --git a/FunctionalBlock.cpp b/FunctionalBlock.cpp
index cb8ceba..51bebe8 100644
--- a/FunctionalBlock.cpp
+++ b/FunctionalBlock.cpp
@@ -41,6 +41,11 @@ bool FunctionalBlock::isFunctionalBlock() {
   return true;
 }
 
+bool FunctionalBlock::isSourceBlock() {
+  if (parent == NULL) return true;
+  return false;
+}
+
 void FunctionalBlock::populate() {
   int i;
   BlockParameter* p;
diff --git a/FunctionalBlock.h b/FunctionalBlock.h
index 1360244..c122dcf 100644
--- a/FunctionalBlock.h
+++ b/FunctionalBlock.h
@@ -32,6 +32,7 @@ public:
 
   // testers
   bool isFunctionalBlock();
+  bool isSourceBlock(); //! a source block has no parent
 
   // others
 
diff --git a/FunctionalInterface.cpp b/FunctionalInterface.cpp
index d34cc8d..7224b3f 100644
--- a/FunctionalInterface.cpp
+++ b/FunctionalInterface.cpp
@@ -99,21 +99,26 @@ bool FunctionalInterface::canConnectTo(AbstractInterface *iface) {
      2 - iface is owned by the parent group of the block that owns this
         2.1 - this is an output, iface is an output of the group
         2.2 - both are inout
+     3 - this is owned by a source block and iface is owned by the top group
 
   */
   if (direction == Input) return false;
   if (iface->isReferenceInterface()) return false;
   if (iface->getConnectedFrom() != NULL) return false;
-
+  // first case: interface of blocks within the same group
   if (getOwner()->getParent() == iface->getOwner()->getParent()) {
 
     if ((direction == Output) && (iface->getDirection() == Input)) return true;
     if ((direction == InOut) && (iface->getDirection() == InOut)) return true;
   }
+  // second case: iface = interface of the group that contains owner of this
   else if (getOwner()->getParent() == iface->getOwner()) {
     if ((direction == Output) && (iface->getDirection() == Output)) return true;
     if ((direction == InOut) && (iface->getDirection() == InOut)) return true;
   }
+  else if ((getOwner()->isSourceBlock()) && (iface->getOwner()->isTopGroupBlock())) {
+    if ((direction == Output) && (iface->getDirection() == Input)) return true;
+  }
 
   return false;
 
diff --git a/GroupBlock.cpp b/GroupBlock.cpp
index e5d3b21..7995e62 100644
--- a/GroupBlock.cpp
+++ b/GroupBlock.cpp
@@ -34,6 +34,10 @@ bool GroupBlock::isGroupBlock() {
   return true;
 }
 
+bool GroupBlock::isTopGroupBlock() {
+  return topGroup;
+}
+
 void GroupBlock::setParent(AbstractBlock *_parent) {
   parent = _parent;
   if (parent != NULL) {
diff --git a/GroupBlock.h b/GroupBlock.h
index e07fd90..0e1c894 100644
--- a/GroupBlock.h
+++ b/GroupBlock.h
@@ -27,6 +27,7 @@ public:
 
   // testers
   bool isGroupBlock();
+  bool isTopGroupBlock();
   inline bool isTop() { return topGroup; }
 
   // others
diff --git a/GroupInterface.cpp b/GroupInterface.cpp
index 7fc8745..b59eb23 100644
--- a/GroupInterface.cpp
+++ b/GroupInterface.cpp
@@ -38,6 +38,7 @@ bool GroupInterface::canConnectTo(AbstractInterface *iface) {
      3 - this is owned by a group and iface by its parent group
         2.1 - this is an output, iface is an output of the group
         2.2 - both are inout
+     
 
 
   */
@@ -57,6 +58,7 @@ bool GroupInterface::canConnectTo(AbstractInterface *iface) {
     if ((direction == Output) && (iface->getDirection() == Output)) return true;
     if ((direction == InOut) && (iface->getDirection() == InOut)) return true;
   }
+  
 
   return false;
 }
@@ -78,6 +80,7 @@ bool GroupInterface::canConnectFrom(AbstractInterface *iface) {
      3 - this is owned by a group and iface by its parent group
         2.1 - this is an input, iface is an input of the group
         2.2 - both are inout
+     4 - this is owned by top group and iface is an output of a source block           
   */
   if (iface->isReferenceInterface()) return false;
   if (getConnectedFrom() != NULL) return false;
@@ -95,6 +98,9 @@ bool GroupInterface::canConnectFrom(AbstractInterface *iface) {
     if ((direction == Input) && (iface->getDirection() == Input)) return true;
     if ((direction == InOut) && (iface->getDirection() == InOut)) return true;
   }
+  else if ((getOwner()->isTopGroupBlock()) && (iface->getOwner()->isSourceBlock())) {
+    if ((direction == Input) && (iface->getDirection() == Output)) return true;
+  }
 
   return false;
 }
diff --git a/GroupItem.cpp b/GroupItem.cpp
index c965452..e219f4c 100644
--- a/GroupItem.cpp
+++ b/GroupItem.cpp
@@ -383,12 +383,7 @@ void GroupItem::mousePressEvent(QGraphicsSceneMouseEvent *event) {
 
   dispatcher->setCurrentGroupWidget(getScene()->getGroupWidget());
 
-  /* NOTE : commneted because group interface are normally
-     created and the connected directly to a block within
-     the group. Furthermore, there can be a single connection
-     from a groupe interface.
-
-  if ((mode == GroupScene::AddConnection) && (params->cursorState == Parameters::CursorOnInterface)) {
+  if ((refBlock->isTopGroupBlock()) && (mode == GroupScene::AddConnection) && (params->cursorState == Parameters::CursorOnInterface)) {
     InterfaceItem *inter = getInterfaceFromCursor(x,y);
     if (inter != NULL) {
 
@@ -406,9 +401,8 @@ void GroupItem::mousePressEvent(QGraphicsSceneMouseEvent *event) {
         }
       }
     }
-  }
-  */
-  if (mode == GroupScene::ItemEdition) {
+  }  
+  else if (mode == GroupScene::ItemEdition) {
 
     if (params->cursorState == Parameters::CursorOnInterface) {
       InterfaceItem *inter = getInterfaceFromCursor(x,y);
@@ -433,12 +427,7 @@ void GroupItem::mouseReleaseEvent(QGraphicsSceneMouseEvent  *event) {
 
   int mode = getScene()->getEditionMode();
 
-  /* NOTE : commneted because group interface are normally
-     created and the connected directly to a block within
-     the group. Furthermore, there can be a single connection
-     from a groupe interface.
-
-  if (mode == GroupScene::AddConnection) {
+  if ((refBlock->isTopGroupBlock()) && (mode == GroupScene::AddConnection)) {
 
     if (params->editState == Parameters::EditStartConnection) {
       params->setEditState(Parameters::EditStartConnection);
@@ -456,7 +445,7 @@ void GroupItem::mouseReleaseEvent(QGraphicsSceneMouseEvent  *event) {
     else if (params->editState == Parameters::EditCloseConnection) {
       InterfaceItem* iface1 = getScene()->getSelectedInterface(1);
       InterfaceItem* iface2 = getScene()->getSelectedInterface(2);
-      bool ok = dispatcher->connect(iface1,iface2);
+      bool ok = dispatcher->createConnectionItem(iface1,iface2);
       if (ok) {
         iface1->selected = false;
         update(iface1->boundingRect());
@@ -465,9 +454,8 @@ void GroupItem::mouseReleaseEvent(QGraphicsSceneMouseEvent  *event) {
         params->setEditState(Parameters::EditNoOperation);
       }
     }
-  }
-  */
-  if (mode == GroupScene::ItemEdition) {
+  }  
+  else if (mode == GroupScene::ItemEdition) {
     currentInterface = NULL;
     setFlag(ItemIsMovable, true);
     params->editState = Parameters::EditNoOperation;
diff --git a/GroupScene.cpp b/GroupScene.cpp
index b24c39c..531f62b 100644
--- a/GroupScene.cpp
+++ b/GroupScene.cpp
@@ -140,15 +140,11 @@ void GroupScene::removeSourceItem(SourceItem* item) {
   sourceItems.removeAll(item);  
 }
 
-void GroupScene::createConnectionItem(InterfaceItem *iface1, InterfaceItem *iface2, bool withinGroup) {
+void GroupScene::createConnectionItem(InterfaceItem *iface1, InterfaceItem *iface2) {
   ConnectionItem* conn = NULL;
-  if (withinGroup) {
-    conn = new ConnectionItem(iface1,iface2, dispatcher, params, groupItem);
-  }
-  else {
-    conn = new ConnectionItem(iface1,iface2, dispatcher, params, NULL);
-    addItem(conn);
-  }
+  
+  conn = new ConnectionItem(iface1,iface2, dispatcher, params);
+  addItem(conn);  
   addConnectionItem(conn);
 }
 
diff --git a/GroupScene.h b/GroupScene.h
index 19185a1..61319df 100644
--- a/GroupScene.h
+++ b/GroupScene.h
@@ -76,7 +76,7 @@ public:
   void removeBoxItem(BoxItem* item);
   
   // ConnectionItem related
-  void createConnectionItem(InterfaceItem* iface1, InterfaceItem* iface2, bool withinGroup = true);
+  void createConnectionItem(InterfaceItem* iface1, InterfaceItem* iface2);
   ConnectionItem* searchConnectionItem(InterfaceItem* iface1, InterfaceItem* iface2);
   void addConnectionItem(ConnectionItem* item);
   void removeConnectionItem(ConnectionItem* item);
diff --git a/InterfaceItem.cpp b/InterfaceItem.cpp
index ff6329e..ff5f5c6 100644
--- a/InterfaceItem.cpp
+++ b/InterfaceItem.cpp
@@ -11,7 +11,7 @@ InterfaceItem::InterfaceItem(double _position,
                              int _orientation,
                              ConnectedInterface *_refInter,
                              AbstractBoxItem* _owner,
-                             Parameters* _params){
+                             Parameters* _params) {
   positionRatio = _position;
   orientation = _orientation;
   refInter = _refInter;
@@ -129,6 +129,12 @@ void InterfaceItem::paint(QPainter *painter) {
     }
 
     // draw names
+    if(selected) {
+      painter->setPen(QPen(Qt::red,2));
+    }    
+    else  {
+      painter->setPen(QPen(Qt::black,1));      
+    }
 
     // reset to normal if at west
     if(orientation == Parameters::West){
@@ -164,33 +170,30 @@ void InterfaceItem::paint(QPainter *painter) {
   }
 }
 
-QPointF InterfaceItem::getEndPointInGroup() {
-  QPointF p;
+QPointF InterfaceItem::getStartPosition() {
+  QPointF p = originPoint;
+  QPointF ownerPos = owner->scenePos();  
+  p += ownerPos;
+  return p;
+}
 
-  if (owner->isGroupItem()) {
-    p = originPoint;
-  }
-  else {
-    double x = owner->x() + originPoint.x();
-    double y = owner->y() + originPoint.y();
-    switch(orientation){
-    case Parameters::East:
-      x += params->arrowWidth+params->arrowLineLength;
-      break;
-    case Parameters::North:
-      y -= params->arrowWidth+params->arrowLineLength;
-      break;
-    case Parameters::West:
-      x -= params->arrowWidth+params->arrowLineLength;
-      break;
-    case Parameters::South:
-      y += params->arrowWidth+params->arrowLineLength;
-      break;
-    }
-    p = QPointF(x,y);
+QPointF InterfaceItem::getEndPosition() {
+  QPointF p = getStartPosition();
+  
+  switch(orientation){
+  case Parameters::East:
+    p.setX(p.x()+params->arrowWidth+params->arrowLineLength);
+    break;
+  case Parameters::North:
+    p.setY(p.y() - params->arrowWidth-params->arrowLineLength);
+    break;
+  case Parameters::West:
+    p.setX(p.x() - params->arrowWidth-params->arrowLineLength);
+    break;
+  case Parameters::South:
+    p.setY(p.y() + params->arrowWidth+params->arrowLineLength);
+    break;
   }
-
-  //cout << "iface end point in group item: " << p.x() << "," << p.y() << endl;
   return p;
 }
 
diff --git a/InterfaceItem.h b/InterfaceItem.h
index ff7b761..77ddf72 100644
--- a/InterfaceItem.h
+++ b/InterfaceItem.h
@@ -38,8 +38,9 @@ public:
   inline int getNameWidth() { return nameWidth; }
   inline int getNameHeight() { return nameHeight; }
   QString getStrOrientation();
-  static int getIntOrientation(QString str);
-  QPointF getEndPointInGroup();
+  static int getIntOrientation(QString str);  
+  QPointF getEndPosition();
+  QPointF getStartPosition();
 
   // setters
   void setOriginPoint();
diff --git a/blast.creator.user b/blast.creator.user
index 9f8479e..da6e731 100755
--- a/blast.creator.user
+++ b/blast.creator.user
@@ -1,10 +1,10 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <!DOCTYPE QtCreatorProject>
-<!-- Written by QtCreator 3.2.1, 2017-05-09T19:54:54. -->
+<!-- Written by QtCreator 3.2.1, 2017-05-09T22:33:21. -->
 <qtcreator>
  <data>
   <variable>EnvironmentId</variable>
-  <value type="QByteArray">{1d077e47-e3a1-47fd-8b12-4de650e39df5}</value>
+  <value type="QByteArray">{c8006d66-d34f-42be-ad10-d0207752286d}</value>
  </data>
  <data>
   <variable>ProjectExplorer.Project.ActiveTarget</variable>
@@ -60,12 +60,12 @@
   <valuemap type="QVariantMap">
    <value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">Desktop</value>
    <value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName">Desktop</value>
-   <value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">{451ee8a3-56ff-4aba-8a8e-3da882cc142e}</value>
+   <value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">{2c9bf876-3476-44eb-8065-1f0844704dda}</value>
    <value type="int" key="ProjectExplorer.Target.ActiveBuildConfiguration">0</value>
    <value type="int" key="ProjectExplorer.Target.ActiveDeployConfiguration">0</value>
    <value type="int" key="ProjectExplorer.Target.ActiveRunConfiguration">0</value>
    <valuemap type="QVariantMap" key="ProjectExplorer.Target.BuildConfiguration.0">
-    <value type="QString" key="ProjectExplorer.BuildConfiguration.BuildDirectory">/localhome/sdomas/Projet/Blast/code/blast</value>
+    <value type="QString" key="ProjectExplorer.BuildConfiguration.BuildDirectory">/home/sdomas/Projet/Blast/code/blast</value>
     <valuemap type="QVariantMap" key="ProjectExplorer.BuildConfiguration.BuildStepList.0">
      <valuemap type="QVariantMap" key="ProjectExplorer.BuildStepList.Step.0">
       <valuelist type="QVariantList" key="GenericProjectManager.GenericMakeStep.BuildTargets">
-- 
2.39.5