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

Private GIT Repository
1st commit of all files
authorStéphane Domas <sdomas@prodigy.iut-bm.univ-fcomte.fr>
Wed, 26 Apr 2017 12:17:46 +0000 (14:17 +0200)
committerStéphane Domas <sdomas@prodigy.iut-bm.univ-fcomte.fr>
Wed, 26 Apr 2017 12:17:46 +0000 (14:17 +0200)
140 files changed:
.gitignore [new file with mode: 0644]
AbstractBlock.cpp [new file with mode: 0644]
AbstractBlock.h [new file with mode: 0644]
AbstractBoxItem.cpp [new file with mode: 0644]
AbstractBoxItem.h [new file with mode: 0644]
AbstractInterface.cpp [new file with mode: 0644]
AbstractInterface.h [new file with mode: 0644]
ArithmeticEvaluator.cpp [new file with mode: 0644]
ArithmeticEvaluator.h [new file with mode: 0644]
BlockCategory.cpp [new file with mode: 0644]
BlockCategory.h [new file with mode: 0644]
BlockImplementation.cpp [new file with mode: 0644]
BlockImplementation.h [new file with mode: 0644]
BlockLibraryTree.cpp [new file with mode: 0644]
BlockLibraryTree.h [new file with mode: 0644]
BlockLibraryWidget.cpp [new file with mode: 0644]
BlockLibraryWidget.h [new file with mode: 0644]
BlockParameter.cpp [new file with mode: 0644]
BlockParameter.h [new file with mode: 0644]
BlockParameterGeneric.cpp [new file with mode: 0644]
BlockParameterGeneric.h [new file with mode: 0644]
BlockParameterPort.cpp [new file with mode: 0644]
BlockParameterPort.h [new file with mode: 0644]
BlockParameterUser.cpp [new file with mode: 0644]
BlockParameterUser.h [new file with mode: 0644]
BlockParameterWishbone.cpp [new file with mode: 0644]
BlockParameterWishbone.h [new file with mode: 0644]
BlockWidget.cpp [new file with mode: 0644]
BlockWidget.h [new file with mode: 0644]
BlocksToConfigureWidget.cpp [new file with mode: 0644]
BlocksToConfigureWidget.h [new file with mode: 0644]
BoxItem.cpp [new file with mode: 0644]
BoxItem.h [new file with mode: 0644]
ConnectedInterface.cpp [new file with mode: 0644]
ConnectedInterface.h [new file with mode: 0644]
ConnectionItem.cpp [new file with mode: 0644]
ConnectionItem.h [new file with mode: 0644]
Dispatcher.cpp [new file with mode: 0644]
Dispatcher.h [new file with mode: 0644]
Exception.cpp [new file with mode: 0644]
Exception.h [new file with mode: 0644]
FunctionalBlock.cpp [new file with mode: 0644]
FunctionalBlock.h [new file with mode: 0644]
FunctionalInterface.cpp [new file with mode: 0644]
FunctionalInterface.h [new file with mode: 0644]
Graph.cpp [new file with mode: 0644]
Graph.h [new file with mode: 0644]
GroupBlock.cpp [new file with mode: 0644]
GroupBlock.h [new file with mode: 0644]
GroupInterface.cpp [new file with mode: 0644]
GroupInterface.h [new file with mode: 0644]
GroupItem.cpp [new file with mode: 0644]
GroupItem.h [new file with mode: 0644]
GroupScene.cpp [new file with mode: 0644]
GroupScene.h [new file with mode: 0644]
GroupWidget.cpp [new file with mode: 0644]
GroupWidget.h [new file with mode: 0644]
InterfaceItem.cpp [new file with mode: 0644]
InterfaceItem.h [new file with mode: 0644]
InterfacePropertiesWindow.cpp [new file with mode: 0644]
InterfacePropertiesWindow.h [new file with mode: 0644]
MainWindow.cpp [new file with mode: 0644]
MainWindow.h [new file with mode: 0644]
Makefile.in [new file with mode: 0644]
Parameters.cpp [new file with mode: 0644]
Parameters.h [new file with mode: 0644]
ParametersWindow.cpp [new file with mode: 0644]
ParametersWindow.h [new file with mode: 0644]
ReferenceBlock.cpp [new file with mode: 0644]
ReferenceBlock.h [new file with mode: 0644]
ReferenceInterface.cpp [new file with mode: 0644]
ReferenceInterface.h [new file with mode: 0644]
Toto.cpp [new file with mode: 0644]
Toto.h [new file with mode: 0644]
blast-tg.odt [new file with mode: 0755]
blast.config [new file with mode: 0755]
blast.cpp [new file with mode: 0644]
blast.creator [new file with mode: 0755]
blast.creator.user [new file with mode: 0755]
blast.files [new file with mode: 0755]
blast.ico [new file with mode: 0755]
blast.includes [new file with mode: 0755]
blast.qrc [new file with mode: 0755]
blast.rc [new file with mode: 0755]
blastconfig.xml [new file with mode: 0644]
blastconfig.xsd [new file with mode: 0644]
block-1I1O.xml [new file with mode: 0644]
block-2I2O.xml [new file with mode: 0644]
block-2INO.xml [new file with mode: 0644]
block.xsd [new file with mode: 0644]
doc/models-tg.pdf [new file with mode: 0644]
doc/models-tg.tex [new file with mode: 0644]
icons/add_block.png [new file with mode: 0644]
icons/add_block.svg [new file with mode: 0644]
icons/add_connection.png [new file with mode: 0644]
icons/add_connection.svg [new file with mode: 0644]
icons/add_group.png [new file with mode: 0644]
icons/add_group.svg [new file with mode: 0644]
icons/add_group_select.png [new file with mode: 0644]
icons/add_group_select.svg [new file with mode: 0644]
icons/add_group_small.png [new file with mode: 0644]
icons/add_group_void.png [new file with mode: 0644]
icons/add_group_void.svg [new file with mode: 0644]
icons/copy.png [new file with mode: 0644]
icons/cut.png [new file with mode: 0644]
icons/delete.png [new file with mode: 0644]
icons/edit_block.png [new file with mode: 0644]
icons/folder_add_16.png [new file with mode: 0644]
icons/inter_add.png [new file with mode: 0644]
icons/link.png [new file with mode: 0644]
icons/load.png [new file with mode: 0644]
icons/new.ico [new file with mode: 0644]
icons/new_block.ico [new file with mode: 0644]
icons/new_block.png [new file with mode: 0644]
icons/open.png [new file with mode: 0644]
icons/paste.png [new file with mode: 0644]
icons/redo-icon.png [new file with mode: 0644]
icons/save-as.png [new file with mode: 0644]
icons/save.png [new file with mode: 0644]
icons/undo.png [new file with mode: 0644]
icons/window_new.png [new file with mode: 0644]
install.sh [new file with mode: 0644]
install.sh.in [new file with mode: 0644]
lib/README.txt [new file with mode: 0644]
lib/implementations/apf27-wb-master_impl.xml [new file with mode: 0644]
lib/implementations/demux_impl.xml [new file with mode: 0644]
lib/implementations/impls.bmf [new file with mode: 0644]
lib/implementations/multadd.vhd [new file with mode: 0644]
lib/implementations/multadd_core.vhd [new file with mode: 0644]
lib/implementations/multadd_ctrl.vhd [new file with mode: 0644]
lib/implementations/multadd_impl.xml [new file with mode: 0644]
lib/references/apf27-wb-master.xml [new file with mode: 0644]
lib/references/demux.xml [new file with mode: 0644]
lib/references/multadd.xml [new file with mode: 0644]
lib/references/references.bmf [new file with mode: 0644]
object-files.txt [new file with mode: 0644]
projectfile.xsd [new file with mode: 0644]
save/sauv.xml [new file with mode: 0644]
save/test.xml [new file with mode: 0644]
testproject.xml [new file with mode: 0644]

diff --git a/.gitignore b/.gitignore
new file mode 100644 (file)
index 0000000..f44bef8
--- /dev/null
@@ -0,0 +1,10 @@
+/archive/*
+/build/*
+/Makefile
+/configure
+*~
+*.aux
+*.log
+*.dvi
+*.bbl
+*.blg
\ No newline at end of file
diff --git a/AbstractBlock.cpp b/AbstractBlock.cpp
new file mode 100644 (file)
index 0000000..6e9cc86
--- /dev/null
@@ -0,0 +1,167 @@
+#include <AbstractBlock.h>\r
+#include <QInputDialog>\r
+#include <QMessageBox>\r
+#include "AbstractInterface.h"\r
+#include "BlockParameter.h"\r
+\r
+AbstractBlock::AbstractBlock() {\r
+  name = "";\r
+  parent = NULL;\r
+}\r
+\r
+AbstractBlock::AbstractBlock(const QString& _name) {\r
+  name = _name;\r
+  parent = NULL;\r
+}\r
+\r
+AbstractBlock::~AbstractBlock() {\r
+\r
+  foreach(AbstractInterface* iface, inputs) {\r
+    delete iface;\r
+  }\r
+  foreach(AbstractInterface* iface, outputs) {\r
+    delete iface;\r
+  }\r
+  foreach(AbstractInterface* iface, bidirs) {\r
+    delete iface;\r
+  }\r
+  inputs.clear();\r
+  outputs.clear();\r
+  bidirs.clear();\r
+  foreach(BlockParameter* p, params) {\r
+    delete p;\r
+  }\r
+  params.clear();\r
+}\r
+\r
+void AbstractBlock::setName(const QString& str) {\r
+  name = str;\r
+}\r
+\r
+void AbstractBlock::setParent(AbstractBlock* _parent) {\r
+  parent = _parent;\r
+}\r
+\r
+bool AbstractBlock::isReferenceBlock() {\r
+  return false;\r
+}\r
+\r
+bool AbstractBlock::isFunctionalBlock() {\r
+  return false;\r
+}\r
+\r
+bool AbstractBlock::isGroupBlock() {\r
+  return false;\r
+}\r
+\r
+void AbstractBlock::addParameter(BlockParameter *param) {\r
+  params.append(param);\r
+}\r
+\r
+\r
+BlockParameter* AbstractBlock::getParameterFromName(QString name) {\r
+  foreach(BlockParameter* p, params) {\r
+    if (p->getName() == name) return p;\r
+  }\r
+  return NULL;\r
+}\r
+\r
+void AbstractBlock::addInterface(AbstractInterface *inter) {\r
+  if(inter->getDirection() == AbstractInterface::Input){\r
+    inputs.append(inter);\r
+  } else if(inter->getDirection() == AbstractInterface::Output){\r
+    outputs.append(inter);\r
+  } else if(inter->getDirection() == AbstractInterface::InOut){\r
+    bidirs.append(inter);\r
+  }\r
+}\r
+\r
+void AbstractBlock::removeInterface(AbstractInterface *inter) {\r
+  /* CAUTION: no check is done about the connection state of this interface\r
+     Thus, if it is still connected to/from, there will be a crash\r
+   */\r
+  if(inter->getDirection() == AbstractInterface::Input){\r
+    inputs.removeAll(inter);\r
+  } else if(inter->getDirection() == AbstractInterface::Output){\r
+    outputs.removeAll(inter);\r
+  } else if(inter->getDirection() == AbstractInterface::InOut){\r
+    bidirs.removeAll(inter);\r
+  }\r
+  delete inter;\r
+}\r
+\r
+void AbstractBlock::defineBlockParam(BlockParameter *param)\r
+{\r
+  cout << "definition of param : " << param->getName().toStdString() << endl;\r
+  bool ok = false;\r
+  QString value = QInputDialog::getText(NULL, "Block parameter", "value for the "+ param->getName() +" parameter of " + param->getOwner()->getName() + "?", QLineEdit::Normal, param->getValue().toString(), &ok);\r
+\r
+  while (!ok && value.isEmpty())\r
+  {\r
+    QMessageBox::critical(NULL, "Error", "You have to insert a value for the parameter or accept the default value !");\r
+    value = QInputDialog::getText(NULL, "Block parameter", "value for the "+ param->getName() +" parameter of " + param->getOwner()->getName() + " ?", QLineEdit::Normal, param->getValue().toString(), &ok);\r
+  }\r
+  param->setValue(value);  \r
+}\r
+\r
+QList<AbstractInterface *> AbstractBlock::getInterfaces() {\r
+  QList<AbstractInterface *> list;\r
+  list.append(inputs);\r
+  list.append(outputs);\r
+  list.append(bidirs);\r
+  return list;\r
+}\r
+\r
+AbstractInterface* AbstractBlock::getIfaceFromName(QString name) {\r
+\r
+  foreach(AbstractInterface* iface, inputs) {\r
+    if (iface->getName() == name) return iface;\r
+  }\r
+  foreach(AbstractInterface* iface, outputs) {\r
+    if (iface->getName() == name) return iface;\r
+  }\r
+  foreach(AbstractInterface* iface, bidirs) {\r
+    if (iface->getName() == name) return iface;\r
+  }\r
+  return NULL;\r
+}\r
+\r
+bool AbstractBlock::isWBConfigurable() {\r
+\r
+  foreach(BlockParameter* p, params) {\r
+    if (p->isWishboneParameter()) return true;\r
+  }\r
+  return false;\r
+}\r
+\r
+QList<BlockParameter *> AbstractBlock::getUserParameters() {\r
+  QList<BlockParameter *> lst;\r
+  foreach(BlockParameter* p, params) {\r
+    if (p->isUserParameter()) lst.append(p);\r
+  }\r
+  return lst;\r
+}\r
+\r
+QList<BlockParameter *> AbstractBlock::getGenericParameters() {\r
+  QList<BlockParameter *> lst;\r
+  foreach(BlockParameter* p, params) {\r
+    if (p->isGenericParameter()) lst.append(p);\r
+  }\r
+  return lst;\r
+}\r
+\r
+QList<BlockParameter *> AbstractBlock::getPortParameters() {\r
+  QList<BlockParameter *> lst;\r
+  foreach(BlockParameter* p, params) {\r
+    if (p->isPortParameter()) lst.append(p);\r
+  }\r
+  return lst;\r
+}\r
+\r
+QList<BlockParameter *> AbstractBlock::getWishboneParameters() {\r
+  QList<BlockParameter *> lst;\r
+  foreach(BlockParameter* p, params) {\r
+    if (p->isWishboneParameter()) lst.append(p);\r
+  }\r
+  return lst;\r
+}\r
diff --git a/AbstractBlock.h b/AbstractBlock.h
new file mode 100644 (file)
index 0000000..2c89cbf
--- /dev/null
@@ -0,0 +1,78 @@
+#ifndef __ABSTRACTBLOCK_H__\r
+#define __ABSTRACTBLOCK_H__\r
+\r
+#include <iostream>\r
+\r
+#include <QtCore>\r
+\r
+class AbstractInterface;\r
+class BlockParameter;\r
+\r
+#define AB_TO_REF(ptr) ((ReferenceBlock*)ptr)\r
+#define AB_TO_FUN(ptr) ((FunctionalBlock*)ptr)\r
+#define AB_TO_GRP(ptr) ((GroupBlock*)ptr)\r
+\r
+using namespace std;\r
+using namespace Qt;\r
+\r
+class AbstractBlock {\r
+\r
+public:  \r
+\r
+  AbstractBlock();\r
+  AbstractBlock(const QString& _name);\r
+  virtual ~AbstractBlock();\r
+\r
+  // getters\r
+  inline QString getName() { return name; }\r
+  inline QList<BlockParameter *> getParameters() { return params; }\r
+  inline QList<AbstractInterface*> getInputs() { return inputs; }\r
+  inline QList<AbstractInterface*> getOutputs() { return outputs; }\r
+  inline QList<AbstractInterface*> getBidirs() { return bidirs; }\r
+  QList<BlockParameter *> getUserParameters();\r
+  QList<BlockParameter *> getGenericParameters();\r
+  QList<BlockParameter *> getPortParameters();\r
+  QList<BlockParameter *> getWishboneParameters();\r
+  inline AbstractBlock* getParent() { return parent; }\r
+  // setters\r
+  void setName(const QString& str);\r
+  virtual void setParent(AbstractBlock* _parent);\r
+\r
+  // testers\r
+  virtual bool isReferenceBlock();\r
+  virtual bool isFunctionalBlock();\r
+  virtual bool isGroupBlock();\r
+  bool isWBConfigurable();\r
+\r
+  // others\r
+  virtual void parametersValidation(QList<AbstractBlock*>* checkedBlocks, QList<AbstractBlock*>* blocksToConfigure) = 0; // ugly but usefull   \r
+\r
+  void addParameter(BlockParameter *param);\r
+  void addInterface(AbstractInterface *inter);\r
+  void removeInterface(AbstractInterface *inter);\r
+  void defineBlockParam(BlockParameter *param);\r
+\r
+  QList<AbstractInterface *> getInterfaces();\r
+  AbstractInterface* getIfaceFromName(QString name);\r
+  BlockParameter* getParameterFromName(QString name);\r
+\r
+protected:\r
+\r
+\r
+  QString name;\r
+\r
+  // parameters\r
+  QList<BlockParameter *> params;\r
+\r
+  // interfaces\r
+  QList<AbstractInterface*> inputs;\r
+  QList<AbstractInterface*> outputs;\r
+  QList<AbstractInterface*> bidirs;\r
+\r
+  // others\r
+\r
+  // NB: only GroupBlock and FunctionalBlock have a real parent\r
+  AbstractBlock* parent;\r
+};\r
+\r
+#endif // __ABSTRACTBLOCK_H__\r
diff --git a/AbstractBoxItem.cpp b/AbstractBoxItem.cpp
new file mode 100644 (file)
index 0000000..0afbe29
--- /dev/null
@@ -0,0 +1,255 @@
+#include "AbstractBoxItem.h"
+
+#include "Parameters.h"
+
+#include "Dispatcher.h"
+#include "InterfaceItem.h"
+#include "ConnectionItem.h"
+
+#include "AbstractBlock.h"
+#include "GroupScene.h"
+#include "AbstractInterface.h"
+#include "ConnectedInterface.h"
+
+
+AbstractBoxItem::  AbstractBoxItem(AbstractBlock *_refBlock, Dispatcher *_dispatcher, Parameters *_params, QGraphicsItem *parent) : QGraphicsItem(parent) {
+  dispatcher = _dispatcher;
+  params = _params;
+  refBlock = _refBlock;
+  QFont fontId("Arial",10);
+  QFontMetrics fmId(fontId);
+  nameWidth = fmId.width(refBlock->getName());
+  nameHeight = fmId.height();
+  nameMargin = 10;
+  ifaceMargin = 10;
+
+  // the six following values will be override in subclass constructors
+  minimumBoxWidth = 0;
+  minimumBoxHeight = 0;
+  boxWidth = 0;
+  boxHeight = 0;
+  totalWidth = 0;
+  totalHeight = 0;
+
+  originPoint = QPointF(0.0,0.0);
+
+  selected = false;
+  currentInterface = NULL;
+  rstClkVisible = false;
+
+  setAcceptHoverEvents(true);
+
+  // NOTE : initInterfaces() is only called in subclasses
+}
+
+AbstractBoxItem::~AbstractBoxItem() {
+  foreach(InterfaceItem* inter, interfaces) {
+    delete inter;
+  }
+  interfaces.clear();
+}
+
+bool AbstractBoxItem::isBoxItem() {
+  return false;
+}
+
+bool AbstractBoxItem::isGroupItem() {
+  return false;
+}
+
+void AbstractBoxItem::initInterfaces()
+{
+  /* TO DO : creating all needed InterfaceItem, with by default, input at west and output at east */
+  int orientation = Parameters::West;
+
+  foreach(AbstractInterface *inter, refBlock->getInterfaces()){
+    if(inter->getPurpose() != AbstractInterface::Wishbone){
+      InterfaceItem *item;
+      if(inter->getDirection() == AbstractInterface::Input){
+        orientation = Parameters::West;
+      } else if(inter->getDirection() == AbstractInterface::Output){
+        orientation = Parameters::East;
+      } else if(inter->getDirection() == AbstractInterface::InOut){
+        orientation = Parameters::North;
+      }
+      item = new InterfaceItem(0.0 , orientation, (ConnectedInterface *)inter, this, params);
+      interfaces.append(item);
+    }
+  }  
+}
+
+InterfaceItem* AbstractBoxItem::searchInterfaceByName(QString name) {
+  foreach(InterfaceItem *inter, interfaces){
+    if(inter->getName() == name)
+      return inter;
+  }
+  return NULL;
+}
+
+InterfaceItem* AbstractBoxItem::searchInterfaceByRef(ConnectedInterface *ref) {
+  foreach(InterfaceItem *inter, interfaces){
+    if(inter->refInter == ref) {
+      return inter;
+    }
+  }
+  return NULL;
+}
+
+void AbstractBoxItem::addInterface(InterfaceItem *i, bool resetPosition) {
+  interfaces.append(i);
+  if (resetPosition) resetInterfacesPosition();
+  updateGeometry();
+  update();
+}
+
+void AbstractBoxItem::removeInterface(InterfaceItem *i) {
+  // NB : removing from model is done in dispatcher
+  interfaces.removeOne(i);
+  delete i;
+
+  //resetInterfacesPosition();
+  updateGeometry();
+  update();
+}
+
+
+void AbstractBoxItem::resetInterfacesPosition() {
+
+  int nbNorth=0, nbSouth=0, nbEast=0, nbWest=0;
+  double cntNorth=1.0,cntSouth=1.0,cntEast=1.0,cntWest=1.0;
+  double positionRatio = 1.0;
+
+
+  foreach(InterfaceItem* inter, interfaces) {
+    // only data interfaces and if needed time and reset
+    if(inter->refInter->getPurpose() == AbstractInterface::Data || inter->getOwner()->isRstClkVisible()){
+      if(inter->getOrientation() == Parameters::North){
+        nbNorth++;
+      } else if(inter->getOrientation() == Parameters::South){
+        nbSouth++;
+      } else if(inter->getOrientation() == Parameters::East){
+        nbEast++;
+      } else if(inter->getOrientation() == Parameters::West){
+        nbWest++;
+      }
+    }
+  }
+
+  foreach(InterfaceItem* inter, interfaces) {
+
+    if(inter->refInter->getPurpose() == AbstractInterface::Data || inter->getOwner()->isRstClkVisible()){
+
+      if(inter->getOrientation() == Parameters::North){
+        positionRatio = cntNorth/(double)(nbNorth+1);
+        cntNorth += 1.0;
+      } else if(inter->getOrientation() == Parameters::South){
+        positionRatio = cntSouth/(double)(nbSouth+1);
+        cntSouth += 1.0;
+      } else if(inter->getOrientation() == Parameters::East){
+        positionRatio = cntEast/(double)(nbEast+1);
+        cntEast += 1.0;
+      } else if(inter->getOrientation() == Parameters::West){
+        positionRatio = cntWest/(double)(nbWest+1);
+        cntWest += 1.0;
+      }
+      inter->setPositionRatio(positionRatio);
+      inter->updatePosition();
+    }
+  }
+}
+
+void AbstractBoxItem::deplaceInterface(QPointF pos) {
+  double positionRatio;
+  if(currentInterface->getOrientation() == Parameters::North || currentInterface->getOrientation() == Parameters::South){
+    if(pos.x() < 0){
+      positionRatio = 0;
+      if(pos.y() > 0 && pos.y() < boxHeight){
+        currentInterface->setOrientation(Parameters::West);
+      }
+    } else if(pos.x() > boxWidth){
+      positionRatio = 1;
+      if(pos.y() > 0 && pos.y() < boxHeight){
+        currentInterface->setOrientation(Parameters::East);
+      }
+    } else {
+      positionRatio = ((double) pos.x())/boxWidth;
+    }
+  } else {
+
+    if(pos.y() < 0){
+      positionRatio = 0;
+      if(pos.x() > 0 && pos.x() < boxWidth){
+        currentInterface->setOrientation(Parameters::North);
+      }
+    } else if(pos.y() > boxHeight){
+      positionRatio = 1;
+      if(pos.x() > 0 && pos.x() < boxWidth){
+        currentInterface->setOrientation(Parameters::South);
+      }
+    } else {
+      positionRatio = ((double) pos.y())/boxHeight;
+    }
+  }
+  currentInterface->setPositionRatio(positionRatio);
+  currentInterface->updatePosition();
+}
+
+QRectF AbstractBoxItem::boundingRect() const {
+  // returns a QRectF that contains the block (i.e the main rectangle, interfaces, title, ...)
+  QPointF p = originPoint - QPointF(nameHeight,nameHeight);
+  QSizeF s(totalWidth+2*nameHeight,totalHeight+2*nameHeight);
+  return QRectF(p,s);
+}
+
+
+/* isInterface() : return true if there are some interfaces
+   with the given orientation (N,S,E,O)
+*/
+bool AbstractBoxItem::isInterfaces(int orientation) const {
+  foreach(InterfaceItem* inter, interfaces) {
+    if (inter->getOrientation() == orientation) return true;
+  }
+  return false;
+}
+
+int AbstractBoxItem::nbInterfacesByOrientation(int orientation) {
+  int nb = 0;
+  foreach(InterfaceItem* inter, interfaces) {
+    if ((inter->visible) && (inter->getOrientation() == orientation)) nb++;
+  }
+  return nb;
+}
+
+void AbstractBoxItem::updateInterfacesAndConnections() {
+
+  // update all interfaces positions
+  foreach(InterfaceItem *item, interfaces){
+    item->updatePosition();
+  }
+  if (getScene() != NULL) {
+    // update all connections from/to this block
+    foreach(ConnectionItem *item, getScene()->getConnectionItems()){
+      if ((item->getFromInterfaceItem()->getOwner() == this) || (item->getToInterfaceItem()->getOwner() == this)) {
+        item->setPathes();
+      }
+    }
+  }
+}
+
+void AbstractBoxItem::setDimension(int x, int y) {
+  boxWidth = x;
+  boxHeight = y;
+}
+
+InterfaceItem* AbstractBoxItem::getInterfaceFromCursor(qreal x, qreal y) {
+
+  foreach(InterfaceItem* inter, interfaces) {
+    if(x > inter->boundingRect().x() && x < (inter->boundingRect().x() + inter->boundingRect().width())){
+      if(y > inter->boundingRect().y() && y < (inter->boundingRect().y() + inter->boundingRect().height())){
+        return inter;
+      }
+    }
+  }
+  /* TO DO : check each interfaces if it contains x,y. If yes, return that interface */
+  return NULL;
+}
diff --git a/AbstractBoxItem.h b/AbstractBoxItem.h
new file mode 100644 (file)
index 0000000..6eeb46c
--- /dev/null
@@ -0,0 +1,112 @@
+#ifndef __ABSTRACTBOXITEM_H__
+#define __ABSTRACTBOXITEM_H__
+
+#include <iostream>
+
+#include <QtCore>
+#include <QtGui>
+#include <QGraphicsItem>
+
+class Dispatcher;
+class InterfaceItem;
+class Parameters;
+class AbstractBlock;
+class GroupScene;
+class ConnectedInterface;
+
+class AbstractBoxItem : public QGraphicsItem {
+
+public:  
+
+  enum BorderType { NoBorder = 0, BorderEast, BorderNorth, BorderWest, BorderSouth, CornerSouthEast, Title};
+  enum ChangeType { Resize = 0, InterfaceMove };
+
+  AbstractBoxItem(AbstractBlock *_refBlock, Dispatcher *_dispatcher, Parameters *_params, QGraphicsItem* parent = Q_NULLPTR);
+
+  virtual ~AbstractBoxItem();
+
+  // getters
+  inline AbstractBlock* getRefBlock() { return refBlock; }
+  inline int getWidth() { return boxWidth;}
+  inline int getHeight() { return boxHeight;}
+  inline int getTotalWidth() { return totalWidth;}
+  inline int getTotalHeight() { return totalHeight; }
+  inline QList<InterfaceItem* > getInterfaces() { return interfaces; }
+  inline InterfaceItem *getCurrentInterface() { return currentInterface; }
+  inline int getId(){ return id; }
+  inline GroupScene* getScene() { return (GroupScene*)(scene()); }
+  inline int getIfaceMargin() { return ifaceMargin; }
+  inline int getNameMargin() { return nameMargin; }
+  inline QPointF getOriginPoint() { return originPoint; }
+
+  // setters
+  inline void setId(int id){ this->id = id; }
+  inline void setSelected(bool _selected) { selected = _selected; }  
+  inline void setRstClkVisible(bool b){ rstClkVisible = b;}
+  void setDimension(int x, int y);
+  inline void setCurrentInterface(InterfaceItem* iface) { currentInterface = iface; }
+
+  // testers
+  virtual bool isBoxItem();
+  virtual bool isGroupItem();  
+  inline bool isSelected() { return selected; }
+  inline bool isRstClkVisible(){ return rstClkVisible;}
+  bool isInterfaces(int orientation) const;
+
+  // others
+
+  void addInterface(InterfaceItem* i, bool resetPosition = false);
+  void removeInterface(InterfaceItem* i);
+  void resetInterfacesPosition();
+  void deplaceInterface(QPointF pos);
+  void updateInterfacesAndConnections();
+
+  InterfaceItem *searchInterfaceByName(QString name);
+  InterfaceItem *searchInterfaceByRef(ConnectedInterface* ref);
+  InterfaceItem* getInterfaceFromCursor(qreal x, qreal y);  
+
+protected: 
+  Dispatcher *dispatcher;
+  Parameters *params;
+  QList<InterfaceItem*> interfaces;
+  /* NOTE : the reference block may be a FunctionalBlock or a GroupBlock, depending on the fact
+  that the real instace will be of FunctionalBlock or GroupBlock
+  */
+  AbstractBlock *refBlock;
+
+  InterfaceItem* currentInterface; // currently clicked interface in ItemEdition mode
+
+  BorderType currentBorder; // which border cursor is on
+  QPointF cursorPosition;
+
+  int id;  
+  int boxWidth; // the width of the main box (without interface, title, ...)
+  int boxHeight; // the height of the main box (without interface, title, ...)
+  int minimumBoxWidth; // minimum width of the main box: may be recomputed if position/number of interface changes
+  int minimumBoxHeight; // minimum height of the main box: may be recomputed if position/number of interface changes
+  int totalWidth; // width and heigth taking into account interfaces,title, ...
+  int totalHeight;  
+  int nameWidth; // the width of the  box (group or block) name in Arial 10
+  int nameHeight; // the height of the name in Arial 10
+  int nameMargin; // the margin around each side of the name
+  int ifaceMargin; // the margin around each side of interfaces' name
+  QPointF originPoint; // the left-top point that is the origin of the bounding box
+
+  bool selected;
+  bool rstClkVisible;
+
+  QPointF currentPosition; // the start point for resize
+
+  virtual void updateMinimumSize() = 0; // modify the minimum size
+  virtual bool updateGeometry(ChangeType type) = 0; // modify the originPoint and the total dimension
+
+  QRectF boundingRect() const;
+  /* pure virtual method inherited from QGraphicsItem :
+    virtual void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget = 0) =0;
+    virtual QRectF boundingRect() const =0;
+  */
+  void initInterfaces();
+  int nbInterfacesByOrientation(int orientation);
+};
+
+#endif // __ABSTRACTBOXITEM_H__
diff --git a/AbstractInterface.cpp b/AbstractInterface.cpp
new file mode 100644 (file)
index 0000000..25cd2d3
--- /dev/null
@@ -0,0 +1,279 @@
+#include "AbstractInterface.h"
+#include "BlockParameterPort.h"
+#include "AbstractBlock.h"
+
+AbstractInterface::AbstractInterface(AbstractBlock* _owner) {
+
+  owner = _owner;
+  name = "";
+  width = "1";
+  direction = Input;
+  purpose = Data;
+  level = Basic;
+  type = Boolean;
+
+}
+
+AbstractInterface::AbstractInterface(AbstractBlock* _owner, const QString& _name, const QString& _type, const QString& _width, int _direction, int _purpose, int _level) {
+
+  owner = _owner;  
+  name = _name;
+  width = _width;
+  direction = _direction;
+  purpose = _purpose;
+  level = _level;
+  if (direction == InOut) {
+    level = Top;
+  }
+  type = typeFromString(_type);
+}
+
+AbstractInterface::AbstractInterface(AbstractInterface* other) {
+  owner = NULL;
+  name = other->name;
+  type = other->type;
+  width = other->width;
+  direction = other->direction;
+  purpose = other->purpose;
+  level = other->level;
+}
+
+AbstractInterface::~AbstractInterface() {
+
+}
+
+bool AbstractInterface::isReferenceInterface() {
+  return false;
+}
+
+bool AbstractInterface::isFunctionalInterface() {
+  return false;
+}
+
+bool AbstractInterface::isGroupInterface() {
+  return false;
+}
+
+QString AbstractInterface::getPurposeString() {
+    QString str;
+    switch(purpose){
+        case AbstractInterface::Data:
+            str = QString("data");
+            break;
+        case AbstractInterface::Clock:
+            str = QString("clock");
+            break;
+        case AbstractInterface::Reset:
+            str = QString("reset");
+            break;
+        case AbstractInterface::Wishbone:
+            str = QString("wishbone");
+            break;
+    }
+    return str;
+}
+
+QString AbstractInterface::getDirectionString() {
+    QString str;
+    switch(direction){
+        case AbstractInterface::Input:
+            str = QString("input");
+            break;
+        case AbstractInterface::Output:
+            str = QString("output");
+            break;
+        case AbstractInterface::InOut:
+            str = QString("inout");
+            break;
+    }
+    return str;
+}
+
+QString AbstractInterface::getLevelString() {
+    QString str;
+    switch(level){
+        case AbstractInterface::Basic:
+            str = QString("basic");
+            break;
+        case AbstractInterface::Top:
+            str = QString("top");
+            break;
+    }
+    return str;
+}
+
+double AbstractInterface::getDoubleWidth() throw(QException) {
+
+  static QString fctName = "AbstractInterface::getDoubleWidth()";
+ #ifdef DEBUG_FCTNAME
+   cout << "call to " << qPrintable(fctName) << endl;
+ #endif
+
+   /*
+    cout << "start AbstractInterface::getDoubleWidth()" << endl;
+    bool ok;
+    double width = getWidth().toDouble(&ok);
+
+    if(!ok){
+      ArithmeticEvaluator *evaluator = new ArithmeticEvaluator;
+      cout << "evaluator created!" << endl;
+      evaluator->setExpression(getWidth());
+      cout << "expression defined!" << endl;
+      foreach(BlockParameter *param, getOwner()->getParameters()){
+        evaluator->setVariableValue(param->getName(), param->getIntValue());
+        cout << "param : " << param->getName().toStdString() << " evaluated!" << endl;
+      }
+      width = evaluator->evaluate();
+      cout << "expression evaluated succefully!" << endl;
+    }
+    cout << "real width : " << width << endl;
+    return width;
+    */
+
+   return 1.0;
+}
+
+void AbstractInterface::setPurpose(int _purpose) {
+  if ((_purpose>=Data) && (_purpose <= Wishbone)) {
+    purpose = _purpose;
+  }
+}
+
+void AbstractInterface::setDirection(int _direction) {
+  if ((_direction > Input) && (_direction <= InOut)) {
+    direction = _direction;
+  }
+  if (direction == InOut) {
+    level = Top;
+  }
+}
+
+void AbstractInterface::setLevel(int _level) {
+  if ((_level >= Basic) << (_level < Top)) {
+    level = _level;
+  }
+  if (direction == InOut) {
+    level = Top;
+  }
+}
+
+
+
+int AbstractInterface::getIntDirection(QString str)
+{
+    if(str == "input") return Input;
+    if(str == "output") return Output;
+    if(str == "inOut") return InOut;
+    return -1;
+}
+
+int AbstractInterface::getIntLevel(QString str)
+{
+    if(str == "basic") return Basic;
+    if(str == "top") return Top;
+    return -1;
+}
+
+QString AbstractInterface::getTypeString() {
+
+  if (type == Boolean) {
+    return "boolean";
+  }
+  else if (type == Natural) {
+    return "natural";
+  }
+  else if (type == Expression) {
+    return "expression";
+  }
+  return "invalid_type";
+}
+
+int AbstractInterface::typeFromString(const QString &_type) {
+
+  int ret;
+  if (_type == "expression") {
+    ret = Expression;
+  }
+  else if (_type == "boolean") {
+    ret = Boolean;
+  }
+  else if (_type == "natural") {
+    ret = Natural;
+  }
+  return ret;
+}
+
+QString AbstractInterface::toVHDL(int context, int flags) throw(Exception) {
+
+  if (isReferenceInterface()) throw(Exception(IFACE_INVALID_TYPE));
+
+  QString msb = width;
+  QString ret="";
+  bool ok;
+  if ((context == BlockParameter::Entity) || (context == BlockParameter::Component)) {
+
+    QString formatBool = "%1 : %2 std_logic";
+    QString formatVector = "%1 : %2 std_logic_vector(%3 downto %4)";
+    if ((flags & BlockParameter::NoComma) == 0) {
+      formatBool.append(";");
+      formatVector.append(";");
+    }
+    QString orientation="";
+    if (direction == Input) {
+      orientation = "in";
+    }
+    else if (direction == Output) {
+      orientation = "out";
+    }
+    else {
+      orientation = "inout";
+    }
+    if (type == Boolean) {
+      ret = formatVector.arg(name).arg(orientation);
+    }
+    else if (type == Natural) {
+      int w = width.toInt(&ok);
+      if (!ok) {
+        throw(Exception(INVALID_VALUE));
+      }
+      else {
+        w -= 1;
+        ret = formatVector.arg(name).arg(orientation).arg(w).arg("0");
+      }
+    }
+    else if (type == Expression) {
+      /* must check the following conditions :
+           - if it contains user/port parameters : must evaluate their numeric value
+           - if it contains generic parameters : just remove the $ -> the expression is not arithmetically evaluated.
+      */
+      QList<BlockParameter*> listGenerics = owner->getGenericParameters();
+      QList<BlockParameter*> listUsers = owner->getUserParameters();
+      QList<BlockParameter*> listPorts = owner->getPortParameters();
+      foreach(BlockParameter* p, listUsers) {
+        QString var = "$";
+        var.append(p->getName());
+        if (width.contains(var)) {
+          int w = p->getValue().toInt(&ok);
+          if (!ok) throw(Exception(INVALID_VALUE));
+          msb.replace(var,p->getValue().toString());
+        }
+      }
+      foreach(BlockParameter* p, listPorts) {
+        QString var = "$";
+        var.append(p->getName());
+        if (width.contains(var)) {
+          BlockParameterPort* pp = (BlockParameterPort*)p;
+          AbstractInterface* iface = owner->getIfaceFromName(pp->getIfaceName());
+
+          int w = p->getValue().toInt(&ok);
+          if (!ok) throw(Exception(INVALID_VALUE));
+          msb.replace(var,p->getValue().toString());
+        }
+      }
+
+      ret = formatVector.arg(name).arg(orientation).arg("toto").arg("0");
+    }
+  }
+  return ret;
+}
+
diff --git a/AbstractInterface.h b/AbstractInterface.h
new file mode 100644 (file)
index 0000000..78414c3
--- /dev/null
@@ -0,0 +1,107 @@
+#ifndef __ABSTRACTINTERFACE_H__
+#define __ABSTRACTINTERFACE_H__
+
+#include <iostream>
+
+#include <QtCore>
+#include <QtGui>
+
+class AbstractBlock;
+
+#include "Exception.h"
+class Exception;
+
+#define AI_TO_REF(ptr) ((ReferenceInterface*)ptr)
+#define AI_TO_FUN(ptr) ((FunctionalInterface*)ptr)
+#define AI_TO_GRP(ptr) ((GroupInterface*)ptr)
+
+using namespace std;
+using namespace Qt;
+
+
+class AbstractInterface {
+
+public :
+
+  enum IfaceWidthType { Expression = 1, Boolean, Natural};
+  enum IfacePurpose { Data = 1, Clock = 2, Reset = 3, Wishbone = 4 };
+  enum IfaceDirection { Input = 1, Output = 2, InOut = 3 };
+  enum IfaceLevel { Basic = 1, Top = 2 };  
+  enum IfaceVHDLContext { Entity = 1, Component = 2, Architecture = 3 }; // NB : 3 is when creating an instance of the block that owns this iface
+  enum IfaceVHDLFlags { NoComma = 1 };
+
+  static int getIntDirection(QString str);
+  static int getIntLevel(QString str);
+
+  AbstractInterface(AbstractBlock* _owner);
+  AbstractInterface(AbstractBlock* _owner, const QString& _name, const QString& _type, const QString& _width, int _direction, int _purpose, int _level);
+  AbstractInterface(AbstractInterface* other);
+  virtual ~AbstractInterface();
+
+  // getters
+  inline QString getName() { return name;}
+  inline int getType() { return type; }
+  QString getTypeString();
+  inline QString getWidth() { return width;}
+  inline int getPurpose() { return purpose;}
+  QString getPurposeString();
+  inline int getDirection() { return direction;}
+  QString getDirectionString();
+  inline int getLevel() { return level;}
+  QString getLevelString();
+  inline AbstractBlock *getOwner() { return owner;}
+
+  double getDoubleWidth() throw(QException);
+
+  //virtual QList<AbstractInterface*> getConnectedTo() = 0;
+
+  /* NB: only GroupInterface and FunctionalInterface have a connectedFrom, so
+     defining getConnectedFrom as pure virtual is normal, usefull even though it is ugly :-)
+   */
+  virtual AbstractInterface* getConnectedFrom() = 0;
+
+  // setters
+  inline void setOwner(AbstractBlock* _owner) { owner = _owner; }
+  inline void setName(const QString& _name) { name = _name; }
+  inline void setWidth(const QString& _width) { width = _width; }
+  inline void setType(int _type) { type = _type;}
+  inline void setType(const QString& _type) { type = typeFromString(_type);}
+  void setPurpose(int _purpose);
+  void setDirection(int _direction);
+  void setLevel(int _level);
+
+  // testers
+  virtual bool isReferenceInterface();
+  virtual bool isFunctionalInterface();
+  virtual bool isGroupInterface();
+  //virtual bool isConnectedTo() = 0;
+  //virtual bool isConnectedFrom() = 0;
+  //virtual bool canConnectTo(AbstractInterface* iface) = 0; // returns yes if this can be connected to iface, no if not
+  //virtual bool canConnectFrom(AbstractInterface* iface) = 0; // returns yes if this can be connected from iface, no if not
+
+  // others
+  virtual AbstractInterface *clone() = 0;
+
+  //virtual bool addConnectedTo(AbstractInterface *inter) = 0;
+  //virtual void removeConnectedTo(AbstractInterface *inter) = 0;
+  //virtual bool setConnectedFrom(AbstractInterface* inter) = 0;
+  //virtual void clearConnectedTo() = 0;
+  //virtual void clearConnections() = 0;
+  //virtual void connectionsValidation(QStack<AbstractInterface*> *interfacetoValidate, QList<AbstractInterface*> *validatedInterfaces) throw(Exception) = 0;
+  int typeFromString(const QString &_type);
+
+  QString toVHDL(int context, int flags) throw(Exception);
+
+protected:
+  QString name;
+  int type;
+  QString width;
+  int purpose;
+  int direction;
+  int level;
+
+  AbstractBlock* owner;
+};
+
+
+#endif // __ABSTRACTINTERFACE_H__
diff --git a/ArithmeticEvaluator.cpp b/ArithmeticEvaluator.cpp
new file mode 100644 (file)
index 0000000..60db08e
--- /dev/null
@@ -0,0 +1,438 @@
+/*-==============================================================-
+
+file : ArithmeticEvaluator.cpp
+
+creation date : 19/05/2015
+
+author : S. Domas (sdomas@univ-fcomte.fr)
+
+description :
+
+supp. infos : saved in UTF-8 [éè]
+
+-==============================================================-*/
+#include "ArithmeticEvaluator.h"
+#include <math.h>
+
+ArithmeticEvaluator::ArithmeticEvaluator() {
+  opMarkers = "+-*/";
+  varMarkers = "$";
+  expression = QStringList();
+  /* CAUTION : function are mandatory using ( ) to encapsulate the operand
+     since spaces are removed. Thus, an expression like sin 10 will lead to
+     sin10 after spaces removal, and thus becomes invalid.
+   */
+  fctMarkers << "sin" << "cos" << "log10" << "log2" << "log" << "ceil" << "floor" << "round";
+}
+
+ArithmeticEvaluator::ArithmeticEvaluator(const QString& _expression) throw(int) {
+  opMarkers = "+-*/";
+  varMarkers = "$";
+  fctMarkers << "sin" << "cos" << "log10" << "log2" << "log" << "ceil" << "floor" << "round";
+  try {
+    setExpression(_expression);
+  }
+  catch(int e) {
+    throw(e);
+  }
+}
+
+void ArithmeticEvaluator::setExpression(const QString& _expression) throw(int) {
+  try {
+    convert(_expression);
+  }
+  catch(int e) {
+    throw(e);
+  }
+}
+
+void ArithmeticEvaluator::print() {
+  foreach(QString elt, expression) {
+    cout << qPrintable(elt) << " ";
+  }
+  cout << endl;
+}
+
+double ArithmeticEvaluator::evalFunction(int indexFunc, double value) {
+  double res = 0.0;
+  if (indexFunc == 0) {
+    res = sin(value);
+  }
+  else if (indexFunc == 1) {
+    res = cos(value);
+  }
+  else if (indexFunc == 2) {
+    res = log10(value);
+  }
+  else if (indexFunc == 3) {
+    res = log2(value);
+  }
+  else if (indexFunc == 4) {
+    res = log(value);
+  }
+  else if (indexFunc == 5) {
+    res = ceil(value);
+  }
+  else if (indexFunc == 6) {
+    res = floor(value);
+  }
+  else if (indexFunc == 7) {
+    res = round(value);
+  }
+
+  return res;
+}
+
+double ArithmeticEvaluator::evaluate() throw(int) {
+  QStack<double> stack;
+  bool ok;
+  double value1,value2;
+  int index = 0;
+  QChar c;
+  foreach(QString elt, expression) {
+    c = elt.at(0);
+    /* CAUTION :
+     \x1bn, n must correspond to the order of QString in fctMarkers.
+     */
+    if (c == '\x1b') {
+      value1 = stack.pop();
+      elt.remove(0,1);
+      int idFunc = elt.toInt(&ok);
+      if ((!ok) || (idFunc < 0) || (idFunc >= fctMarkers.size())) throw(-index);
+      stack.push(evalFunction(idFunc,value1));
+    }
+    else if (varMarkers.contains(c)) {
+      if (!varValues.contains(elt)) throw(-index);
+      stack.push(varValues.value(elt));
+    }
+    else if (opMarkers.contains(c)) {
+      value2 = stack.pop();
+      value1 = stack.pop();
+      if (c == '+') {
+        stack.push(value1+value2);
+      }
+      else if (c == '-') {
+        stack.push(value1-value2);
+      }
+      else if (c == '*') {
+        stack.push(value1*value2);
+      }
+      else if (c == '/') {
+        stack.push(value1/value2);
+      }
+    }
+    else {
+      value1 = elt.toDouble(&ok);
+      if (!ok) throw(-index);
+      stack.push(value1);
+    }
+    index += 1;
+  }
+
+  value1 = stack.pop();
+  if (!stack.isEmpty()) throw(-1);
+  return value1;
+}
+
+/* NOTE :
+  expr is of form:
+  ([ value1 | var1 | func1 | expr1 ] op1 [ value2 | var2 | func2 | expr2 ] op2 ... [ valuen | varn | funcn | exprn ])
+
+  Thus, if the whole expression does not end with ), we encapsulate it with ( ).
+
+  If we don't consider priority among operators, then expression is converted into
+  A1 A2 op1 A3 op2 ... An opn-1
+
+  example : 1+2+3-4-5 -> 1 2 + 3 + 4 -
+
+  If there is priority : * > / > + or - or func, then it is more complex
+
+  example : 1+2+3/4*5-6 -> 1 2 + 3 4 5 * / + 6 -
+
+  with parenthesis, we can do the same recursively
+
+  example : 1+(2+3/4)*5-6 = 1 + expr1 * 5 - 6 -> 1 expr1 5 * + 6 -
+  but expr1 -> 2 3 4 / +, then we finally have 1 2 3 4 / + 5 * + 6 -
+  
+  a func is of form:
+  func_name(expr)
+
+  example : ((1+3-sin(5/6))*(4+(7/3)))
+
+  recursive cross in-depth of the expression leads to do a recursive call each time a ( is encountered.
+  Return of the recursive call is done when ) is encountered.
+  
+ */
+
+void ArithmeticEvaluator::convert(const QString& _expression) throw(int) {
+  QString expr = _expression;
+  QString result="";
+  expr.remove(QChar(' '), Qt::CaseInsensitive);
+  foreach(QString func, fctMarkers) {
+    QString rep = QString("\x1b%1").arg(fctMarkers.indexOf(QRegExp(func)));
+
+    expr.replace(QRegExp(func),rep);
+  }
+  //cout << "packed expr: " << qPrintable(expr) << endl;
+
+  int offset = 0;
+  try {
+    result = convertRecur(expr,&offset);
+    expression = result.split(",");
+  }
+  catch(int err) {
+    cerr << "error while recursive conversion: ";
+    throw(err);
+  }
+
+}
+
+QString ArithmeticEvaluator::convertRecur(const QString& _expression, int *offset) throw(int) {
+  QString result="";
+  QStack<QChar> pile;
+
+  int size;
+  QChar c;
+
+  QString number;
+  QString expr = _expression;
+
+  // testing if it starts by a (,number, variable or function
+  if (!checkAfterOp(expr,*offset-1)) throw(*offset);
+
+  // testing if it starts with a number
+  if ((expr[*offset] == '-') || (expr[*offset].isDigit())) {
+    number = getNumber(expr,*offset,&size);
+    result.append(number+",");
+    *offset += size;
+  }
+  // testing if it starts with a variable
+  else if (varMarkers.contains(expr[*offset])){
+    number = getVariable(expr,*offset,&size);
+    result.append(number+",");
+    *offset += size;
+  }  
+
+  while (*offset<expr.size()) {
+
+    if ( expr[*offset] == '\x1b') {
+      int numFunc = getFunction(expr,*offset,&size);
+      if (numFunc == -1) throw(*offset);
+      *offset += size;
+      if (expr[*offset] != '(') throw(*offset);
+      *offset += 1;
+      result += convertRecur(expr,offset);
+      result += QString("\x1b%1,").arg(numFunc);
+    }
+    else if ( expr[*offset] == '(') {      
+
+      *offset += 1;
+      result += convertRecur(expr,offset);      
+    }
+
+    else if ( expr[*offset] == ')') {      
+
+      if (!checkAfterPar(expr,*offset)) throw(*offset);      
+
+      while (! pile.isEmpty()) {
+        c = pile.pop();
+        result.append(c).append(",");
+      }      
+      *offset += 1;
+      return result;
+    }
+    else if ( (expr[*offset] == '+') || (expr[*offset] == '-')) {
+
+      if (!checkAfterOp(expr,*offset)) throw(*offset);
+
+      // destack operators with equal or greater priority
+      while (!pile.isEmpty()) {
+        c = pile.pop();
+        result.append(c).append(",");
+      }
+      pile.push(expr[*offset]);
+
+      // catch the function, number or variable after operator if next char is not (
+      if ( varMarkers.contains(expr[*offset+1])) {
+        number = getVariable(expr,*offset+1,&size);
+        result.append(number+",");
+        *offset += size+1;
+      }
+      else if (expr[*offset+1].isDigit()) {
+        number = getNumber(expr,*offset+1,&size);
+        result.append(number+",");
+        *offset += size+1;
+      }
+      else {
+        *offset += 1;
+      }      
+    }
+    else if (expr[*offset] == '/') {
+
+      if (!checkAfterOp(expr,*offset)) throw(*offset);
+
+      // destack operator with equal or greater priority (/ and *)
+      c = '1';
+      while ( (pile.isEmpty() == false) && (c != '(') && (c != '+') && (c != '-')) {
+        c = pile.pop();
+        if ( (c=='*') || (c == '/')) {
+          result.append(c).append(",");
+        }
+        else {
+          pile.push(c);
+        }
+      }
+      pile.push(expr[*offset]);
+
+      // catch the number or variable after operator if next char is not (
+      if ( varMarkers.contains(expr[*offset+1])) {
+        number = getVariable(expr,*offset+1,&size);
+        result.append(number+",");
+        *offset += size+1;
+      }
+      else if ( expr[*offset+1].isDigit()) {
+        number = getNumber(expr,*offset+1,&size);
+        result.append(number+",");
+        *offset += size+1;
+      }
+      else {
+        *offset += 1;
+      }
+    }
+    /* CASES with * : a*b, (expra)*b, a*(exprb), (expra)*(exprb)
+       Since * has the most priority, then :
+       a*b and (expra)*b can be translate in ... b *
+       In the two other cases, the * is stacked.
+     */
+    else if ( expr[*offset] == '*') {
+
+      if (!checkAfterOp(expr,*offset)) throw(*offset);
+
+      // catch the number or variable after operator if next char is not (
+      if ( varMarkers.contains(expr[*offset+1])) {
+        number = getVariable(expr,*offset+1,&size);
+        result.append(number+",*,");
+        *offset += size+1;
+      }
+      else if ( expr[*offset+1].isDigit()) {
+        number = getNumber(expr,*offset+1,&size);
+        result.append(number+",*,");
+        *offset += size+1;
+      }
+      else {
+        *offset += 1;
+        pile.push('*');
+      }
+    }
+  } 
+
+  while (pile.isEmpty() == false) {
+
+    c = pile.pop();
+    result.append(c).append(",");
+  }
+  result.chop(1);
+  return result;
+}
+
+QString ArithmeticEvaluator::getNumber(const QString& _expression, int offset, int *size) {
+  int i = offset;
+  QString number="";
+  *size = 0;
+  if (_expression[i] == '-') {
+    number.append('-');
+    i += 1;
+    *size = 1;
+  }
+
+  while (_expression[i].isDigit()) {
+    number.append(_expression[i]);
+    i += 1;
+    *size += 1;
+  }
+
+  // test if it's a floatting point value
+  if (_expression[i] == '.') {
+    number.append(".");
+    i += 1;
+    *size += 1;
+    while (_expression[i].isDigit()) {
+      number.append(_expression[i]);
+      i += 1;
+      *size += 1;
+    }
+  }
+  return number;
+}
+
+QString ArithmeticEvaluator::getVariable(const QString& _expression, int offset, int *size) {
+  int i = offset;
+  QString number="";
+  *size = 0;
+  if (varMarkers.contains(_expression[i])) {
+    number.append(_expression[i]);
+    i += 1;
+    *size = 1;
+  }
+
+  while ((_expression[i].isLetterOrNumber()) || (_expression[i] == '-') || (_expression[i] == '_')) {
+    number.append(_expression[i]);
+    i += 1;
+    *size += 1;
+  }
+
+  return number;
+}
+
+int ArithmeticEvaluator::getFunction(const QString& _expression, int offset, int *size) {
+  int numFunc = -1;
+  int i = offset;
+  QString number="";
+  *size = 0;
+  if (_expression[i] != '\x1b') return -1;
+  i+= 1;
+  *size += 1;
+
+  while (_expression[i].isDigit()) {
+    number.append(_expression[i]);
+    i += 1;
+    *size += 1;
+  }
+  bool ok;
+  numFunc = number.toInt(&ok);
+  if ((!ok) || (numFunc >= fctMarkers.size())) return -1;
+  return numFunc;
+}
+
+bool ArithmeticEvaluator::checkAfterOp(const QString& _expression, int offset) {
+  int size;
+  if (offset+1 >= _expression.size()) return false;
+
+  if (_expression[offset+1] == '(') return true;
+  else if (_expression[offset+1].isDigit()) return true;
+  else if (_expression[offset+1] == '-') {
+    if ((offset+2 < _expression.size()) && (_expression[offset+2].isDigit())) return true;
+  }
+  else if (varMarkers.contains(_expression[offset+1])) {
+    if ((offset+2 < _expression.size()) && (_expression[offset+2].isLetterOrNumber())) return true;
+  }
+  else if (getFunction(_expression, offset+1,&size) != -1) {
+    return true;
+  }
+
+  return false;
+}
+
+bool ArithmeticEvaluator::checkAfterPar(const QString& _expression, int offset) {
+  if (offset >= _expression.size()) return false;
+  // if ) is the last char of the expression : OK
+  if (offset == _expression.size()-1) return true;
+
+  if (_expression[offset+1] == ')') return true;
+  else if (_expression[offset+1] == '+') return true;
+  else if (_expression[offset+1] == '-') return true;
+  else if (_expression[offset+1] == '*') return true;
+  else if (_expression[offset+1] == '/') return true;
+
+  return false;
+}
diff --git a/ArithmeticEvaluator.h b/ArithmeticEvaluator.h
new file mode 100644 (file)
index 0000000..f6d478b
--- /dev/null
@@ -0,0 +1,60 @@
+/*-==============================================================-
+
+file : ArithmeticEvaluator.h
+
+creation date : 19/05/2015
+
+author : S. Domas (sdomas@univ-fcomte.fr)
+
+description : 
+
+supp. infos : saved in UTF-8 [éè]
+
+-==============================================================-*/
+#ifndef __ARITHMETICEVALUATOR_H__
+#define __ARITHMETICEVALUATOR_H__
+
+#include <iostream>
+#include <fstream>
+
+#include <QtCore>
+
+
+using namespace std;
+using namespace Qt;
+
+class ArithmeticEvaluator {
+
+public:
+
+  ArithmeticEvaluator();
+  ArithmeticEvaluator(const QString& _expression) throw(int);
+
+  void setExpression(const QString& _expression) throw(int);
+  inline void setVariablesValue(const QHash<QString,double>& _varValues) { varValues =  _varValues; }
+  inline void setVariableValue(const QString& var, double value) { varValues.insert(var,value); }
+  inline void setVariableMarkers(const QString& _markers) { varMarkers = _markers; }
+
+  void print();
+  double evaluate() throw(int);
+
+protected:
+  QStringList expression;
+  QHash<QString,double> varValues;
+  QString varMarkers; // a sequence of symbols that are allowed to start a variable. $ is by default
+  QString opMarkers; // a sequence if symbols used as operators. +-*/ is the hard-coded default
+  QStringList fctMarkers;
+
+  void convert(const QString& _expression) throw(int);
+  QString convertRecur(const QString& _expression, int* offset) throw(int);
+  QString getNumber(const QString& _expression, int offset, int *size);
+  QString getVariable(const QString& _expression, int offset, int *size);
+  int getFunction(const QString& _expression, int offset, int *size);
+  bool checkAfterOp(const QString& _expression, int offset);
+  bool checkAfterPar(const QString& _expression, int offset);
+
+  double evalFunction(int indexFunc, double value);
+
+};
+
+#endif //__ARITHMETICEVALUATOR_H__
diff --git a/BlockCategory.cpp b/BlockCategory.cpp
new file mode 100644 (file)
index 0000000..0de4d86
--- /dev/null
@@ -0,0 +1,47 @@
+#include "BlockCategory.h"\r
+\r
+BlockCategory::BlockCategory(QString _name, int _id, BlockCategory* _parent) {\r
+  name = _name;\r
+  id = _id;\r
+  parent = _parent;\r
+}\r
+\r
+void BlockCategory::addChild(BlockCategory* child) {\r
+    childs.append(child);\r
+}\r
+\r
+\r
+\r
+BlockCategory* BlockCategory::getChild(QString name) {\r
+  QListIterator<BlockCategory *> iter(childs);\r
+  BlockCategory* item = NULL;\r
+  while(iter.hasNext()) {\r
+    item = iter.next();\r
+    if (item->name == name) return item;\r
+  }\r
+  return NULL;\r
+}\r
+\r
+BlockCategory* BlockCategory::getChild(int index) {\r
+  if ((index >=0) && (index < childs.size()) ) {\r
+    return childs.at(index);\r
+  }\r
+  return NULL;\r
+}\r
+\r
+QList<BlockCategory *> BlockCategory::getAllChilds()\r
+{\r
+    return childs;\r
+}\r
+\r
+ReferenceBlock *BlockCategory::getBlock(int index) {\r
+    if ((index >=0) && (index < blocks.size()) ) {\r
+    return blocks.at(index);\r
+  }\r
+  cout << "block null!" << endl;\r
+  return NULL;\r
+}\r
+\r
+QDomElement BlockCategory::save(QDomDocument &doc) {\r
+}\r
+\r
diff --git a/BlockCategory.h b/BlockCategory.h
new file mode 100644 (file)
index 0000000..78f646e
--- /dev/null
@@ -0,0 +1,50 @@
+#ifndef BLOCKCATEGORY_H\r
+#define BLOCKCATEGORY_H\r
+\r
+#include <iostream>\r
+\r
+#include <QtCore>\r
+#include <QtXml>\r
+#include "ReferenceBlock.h"\r
+class ReferenceBlock;\r
+\r
+using namespace std;\r
+using namespace Qt;\r
+\r
+class Block;\r
+\r
+class BlockCategory {\r
+\r
+public :\r
+  BlockCategory(QString _name, int _id, BlockCategory* _parent = NULL);\r
+  int id;\r
+  // getters\r
+  inline int getId() { return id; }\r
+  inline QString getName() { return name; }\r
+  inline BlockCategory* getParent() { return parent; }\r
+  inline QList<BlockCategory *> getChilds() { return childs; }\r
+  BlockCategory* getChild(QString name);\r
+  BlockCategory* getChild(int index);\r
+  QList<BlockCategory *> getAllChilds();\r
+  inline QList<ReferenceBlock*> getBlocks() { return blocks; }\r
+  ReferenceBlock *getBlock(int index);\r
+\r
+  // setters\r
+  void addChild(BlockCategory* child);\r
+  inline void setParent(BlockCategory* _parent) { parent = _parent; }\r
+\r
+  // I/O\r
+  QDomElement save(QDomDocument &doc);  \r
+\r
+  BlockCategory *getRoot();\r
+\r
+  //int id;\r
+  QList<BlockCategory *> childs;\r
+  BlockCategory* parent;\r
+  QList<ReferenceBlock*> blocks;\r
+private:\r
+  QString name;\r
+\r
+};\r
+\r
+#endif // BLOCKCATEGORY_H\r
diff --git a/BlockImplementation.cpp b/BlockImplementation.cpp
new file mode 100644 (file)
index 0000000..571b72b
--- /dev/null
@@ -0,0 +1,560 @@
+#include "BlockImplementation.h"\r
+\r
+#include "FunctionalBlock.h"\r
+#include "ReferenceBlock.h"\r
+#include "ReferenceInterface.h"\r
+#include "FunctionalInterface.h"\r
+#include "BlockParameter.h"\r
+\r
+\r
+BlockImplementation::BlockImplementation(const QString& _xmlFile) {\r
+  xmlFile = _xmlFile;  \r
+\r
+  evaluator = new ArithmeticEvaluator;\r
+  evaluator->setVariableMarkers("@$");\r
+}\r
+\r
+BlockImplementation::BlockImplementation(const QString& _xmlFile, const QString &_referenceXml, const QString &_referenceMd5) {\r
+  xmlFile = _xmlFile;  \r
+  referenceXml = _referenceXml;\r
+  referenceMd5 = _referenceMd5;\r
+}\r
+\r
+void BlockImplementation::generateVHDL(FunctionalBlock* _block, const QString &path) throw(Exception) {\r
+\r
+  block = _block;\r
+\r
+  QFile implFile(xmlFile);\r
+\r
+  // reading in into QDomDocument\r
+  QDomDocument document("implFile");\r
+\r
+  if (!implFile.open(QIODevice::ReadOnly)) {\r
+    throw(Exception(IMPLFILE_NOACCESS));\r
+  }\r
+  if (!document.setContent(&implFile)) {\r
+    implFile.close();\r
+    throw(Exception(IMPLFILE_NOACCESS));\r
+  }\r
+  implFile.close();\r
+\r
+  bool genController = false;\r
+  QString coreFile = "";\r
+  QString controllerFile = "";\r
+\r
+  if (reference->isWBConfigurable()) {\r
+    genController = true;\r
+    controllerFile = path;\r
+    controllerFile.append(block->getName());\r
+    controllerFile.append("_ctrl.vhd");    \r
+  }\r
+  else {\r
+    controllerFile = "nofile.vhd";    \r
+  }\r
+  coreFile = path;\r
+  coreFile.append(block->getName());\r
+  coreFile.append(".vhd");\r
+\r
+  QFile vhdlCore(coreFile);\r
+  QFile vhdlController(controllerFile);\r
+\r
+  if (!vhdlCore.open(QIODevice::WriteOnly)) {\r
+    throw(Exception(VHDLFILE_NOACCESS));\r
+  }\r
+\r
+  if (genController) {\r
+    if (!vhdlController.open(QIODevice::WriteOnly)) {\r
+      throw(Exception(VHDLFILE_NOACCESS));\r
+    }\r
+  }\r
+  QTextStream outCore(&vhdlCore);\r
+  QTextStream outController;\r
+  if (genController) {\r
+    outController.setDevice(&vhdlController);\r
+  }\r
+\r
+  try {\r
+\r
+\r
+    //Get the root element\r
+    QDomElement impl = document.documentElement();\r
+    QDomElement eltComments = impl.firstChildElement("comments");\r
+    generateComments(eltComments, coreFile, outCore);\r
+    QDomElement eltLibs = eltComments.nextSiblingElement("libraries");\r
+    generateLibraries(eltLibs, outCore);\r
+    generateEntity(outCore, genController);\r
+    QDomElement eltArch = eltLibs.nextSiblingElement("architecture");\r
+    generateArchitecture(eltArch, outCore);\r
+    if (genController) {\r
+      generateController(outController);\r
+    }\r
+  }\r
+  catch(Exception err) {\r
+    throw(err);\r
+  }\r
+\r
+  vhdlCore.close();\r
+  vhdlController.close();\r
+}\r
+\r
+// This function generates the comments part of the VHDL document\r
+void BlockImplementation::generateComments(QDomElement &elt, QString coreFile, QTextStream& out) throw(Exception) {\r
+\r
+  for(int i = 0; i < 50; i++) {\r
+    out << "--";\r
+  }\r
+  out << "\n--\n";\r
+  QString fileName = coreFile;\r
+  out << "--  File        : " << fileName << "\n";\r
+  out << "--\n";\r
+  QDomElement eltAuthor = elt.firstChildElement("author");\r
+  QString firstName = eltAuthor.attribute("firstname","");\r
+  QString lastName = eltAuthor.attribute("lastname","");\r
+  QString mail = eltAuthor.attribute("mail","");\r
+  out << "--  Author(s)   : "<<firstName+" "<<lastName<<" ("<<mail<<")\n";\r
+  out << "--\n";\r
+  QDomElement eltDate = eltAuthor.nextSiblingElement("date");\r
+  QString crea = eltDate.attribute("creation","");\r
+  out << "--  Creation Date   : "<<crea<<"\n";\r
+  out << "--\n";\r
+  QDomElement eltRelated = eltDate.nextSiblingElement("related_files");\r
+  QString relateds = eltRelated.attribute("list","");\r
+  out << "--  Related files   :\n"<<relateds<<"\n";\r
+  out << "--\n";\r
+  QDomElement eltDesc = eltRelated.nextSiblingElement("description");\r
+  QDomElement desc = eltDesc.firstChildElement();\r
+  QString descTxt = desc.text();\r
+  out << "--  Decription      :\n"<<descTxt<<"\n";\r
+  out << "--\n";\r
+  QDomElement eltNote = eltDesc.nextSiblingElement("description");\r
+  QDomElement note = eltNote.firstChildElement();\r
+  QString noteTxt = note.text();\r
+  out << "--  Note          :\n"<<noteTxt<<"\n";\r
+  out << "--\n";\r
+  for(int i = 0; i < 50; i++) {\r
+    out << "--";\r
+  }\r
+  out << "\n\n";\r
+}\r
+\r
+// This function generates the library part of the VHDL document\r
+void BlockImplementation::generateLibraries(QDomElement &elt, QTextStream& out) throw(Exception) {\r
+\r
+  QDomNodeList listLib = elt.elementsByTagName("library");\r
+  for(int i = 0; i < listLib.length(); i++) {\r
+    QDomNode nodeLib = listLib.item(i);\r
+    QDomElement eltLib = nodeLib.toElement();\r
+    QString nameLib = eltLib.attribute("name", "");\r
+    out << "library " << nameLib << ";\n";\r
+    QDomNodeList listPack = eltLib.elementsByTagName("package");\r
+    for(int j = 0; j < listPack.length(); j++) {\r
+      QDomNode nodePack = listPack.item(j);\r
+      QDomElement eltPack = nodePack.toElement();\r
+      QString namePack = eltPack.attribute("name", "");\r
+      QString usePack = elt.attribute("use","");\r
+      out << "use " << nameLib << "." << namePack << "." << usePack << ";\n";\r
+    }\r
+    out << "\n";\r
+  }\r
+}\r
+\r
+// This function generates the entity part of the VHDL document\r
+void BlockImplementation::generateEntity(QTextStream& out, bool hasController) throw(Exception) {\r
+\r
+  int i=0;\r
+  nameEnt = reference->getName();\r
+  //QList<BlockParameter*> listParams = reference->getParameters();\r
+  QList<AbstractInterface*> listInputs = reference->getInputs();\r
+  QList<AbstractInterface*> listOutputs = reference->getOutputs();\r
+  QList<AbstractInterface*> listBidirs = reference->getBidirs();\r
+  QString typePort, namePort;\r
+\r
+  out << "entity " << nameEnt << " is\n";\r
+\r
+\r
+  /* TODO : rewrite the generation to take into acocunt the new object hierarchy */\r
+\r
+  // Generation of the generics\r
+  QList<BlockParameter*> listGenerics = reference->getGenericParameters();\r
+  if ((!listGenerics.isEmpty()) || (hasController)) {\r
+    out << "  generic (" << endl;\r
+    if (hasController) {\r
+      out << "    wb_data_width : integer = 16;" << endl;\r
+      out << "    wb_addr_width : integer = 12";\r
+      if (!listGenerics.isEmpty()) out << ";";\r
+      out << endl;\r
+    }\r
+    for(i=0;i<listGenerics.size()-1;i++) {\r
+      out << "    " << listGenerics.at(i)->toVHDL(BlockParameter::Entity, 0);\r
+    }\r
+    out << "    " << listGenerics.at(i)->toVHDL(BlockParameter::Entity,BlockParameter::NoComma);\r
+\r
+    out << "    );" << endl;\r
+  }\r
+\r
+  out << "  port (" << endl;\r
+\r
+  // Generation of the clk & rst signals\r
+  out << "    -- clk/rst" << endl;\r
+  for(int i = 0; i < listInputs.size(); i++) {\r
+    if(listInputs.at(i)->getPurpose() == AbstractInterface::Clock || listInputs.at(i)->getPurpose() == AbstractInterface::Reset) {\r
+      out << "    " << listInputs.at(i)->getName() << " : in std_logic;" << endl;\r
+    }\r
+  }\r
+\r
+  if (hasController) {\r
+    // Generation of the wishbone signals\r
+    out << "    -- registers r/w via wishbone" << endl;\r
+    QList<BlockParameter*> listWB = reference->getWishboneParameters();\r
+    for(i=0;i<listWB.size()-1;i++) {\r
+      out << "    " << listWB.at(i)->toVHDL(BlockParameter::Entity, 0);\r
+    }\r
+    out << "    " << listWB.at(i)->toVHDL(BlockParameter::Entity,BlockParameter::NoComma);\r
+  }\r
+\r
+\r
+  // Generation of the data signals\r
+  out << "-- data ports\n";\r
+  for(int i = 0; i < listInputs.size(); i++) {\r
+    namePort = getIfaceUserName(reference->AbstractBlock::getIfaceFromName(listInputs.at(i)->getName()));\r
+    if(listInputs.at(i)->getWidth().compare("1"))\r
+      typePort = "std_logic";\r
+    else\r
+      typePort = calculateWidth(listInputs.at(i)->getWidth());\r
+    if(listInputs.at(i)->getPurpose() == 1)\r
+      out << namePort << " : in std_logic_vector(" << typePort << " -1 downto 0) ;\n";\r
+  }\r
+\r
+  for(int i = 0; i < listOutputs.size(); i++) {\r
+    namePort = getIfaceUserName(reference->AbstractBlock::getIfaceFromName(listOutputs.at(i)->getName()));\r
+    if(listOutputs.at(i)->getWidth().compare("1"))\r
+      typePort = "std_logic";\r
+    else\r
+      typePort = calculateWidth(listOutputs.at(i)->getWidth());\r
+    if(listOutputs.at(i)->getPurpose() == 1)\r
+      out << namePort << " : out std_logic_vector(" << typePort << " -1 downto 0) ;\n";\r
+  }\r
+\r
+  for(int i = 0; i < listBidirs.size(); i++) {\r
+    namePort = getIfaceUserName(reference->AbstractBlock::getIfaceFromName(listBidirs.at(i)->getName()));\r
+    if(listBidirs.at(i)->getWidth().compare(("1")))\r
+      typePort = "std_logic";\r
+    else\r
+      typePort = calculateWidth((listBidirs.at(i)->getWidth()));\r
+    if(listBidirs.at(i)->getPurpose() == 1)\r
+      out << namePort << " : inout std_logic_vector(" << typePort << " -1 downto 0) ;\n";\r
+  }\r
+}\r
+\r
+// This function generates the architecture part of the VHDL document\r
+void BlockImplementation::generateArchitecture(QDomElement &elt, QTextStream& out) throw(Exception) {\r
+\r
+  QString expr;\r
+  QDomElement eltArch = elt.nextSiblingElement("architecture");\r
+  out << "architecture " << nameEnt <<"_1 of " << nameEnt << "is\n";\r
+  QString implText = eltArch.text();\r
+  QStringList listLine = implText.split("\n");\r
+  for(int i =0; i < listLine.size(); i++) {\r
+    if(listLine.at(i).contains(QRegularExpression("@foreach{")) != -1) {\r
+      while(listLine.at(i).compare("@endforeach") != -1) {\r
+        expr = expr + listLine.at(i) + '\n';\r
+        i++;\r
+      }\r
+      expr = expr + listLine.at(i);\r
+      out << evalComplex(expr, 1) << '\n';\r
+    }\r
+    if(listLine.at(i).contains(QRegularExpression("@caseeach{")) != -1) {\r
+      while(listLine.at(i).compare("@endcaseeach") != -1) {\r
+        expr = expr + listLine.at(i) + '\n';\r
+        i++;\r
+      }\r
+      expr = expr + listLine.at(i);\r
+      out << evalComplex(expr, 2) << '\n';\r
+    }\r
+\r
+    if(listLine.at(i).contains('@') == -1)\r
+      out << listLine.at(i) << "\n";\r
+    else\r
+      out << eval(listLine.at(i), out) << "\n";\r
+  }\r
+}\r
+\r
+void BlockImplementation::generateController(QTextStream &out) throw(Exception) {\r
+}\r
+\r
+QString BlockImplementation::eval(QString line, QTextStream& out) {\r
+  QString res, s, begLine, endLine, expr;\r
+  evaluator->setExpression(line);\r
+  QRegExp *rxString = new QRegExp("(.*)@{(.*)}(.*)");\r
+  QRegExp *rxValue = new QRegExp("(.*)@val{(.*)}(.*)");\r
+  QRegExp *rxExpr = new QRegExp(".*@eval{(.*)}.*");\r
+\r
+  int nbAt = line.count('@');\r
+  while(nbAt != 0) {\r
+    for(int i = 0; i < line.size(); i++) {\r
+      if(rxString->indexIn(line)) {\r
+        begLine = rxString->cap(1);\r
+        s = rxString->cap(2);\r
+        endLine = rxString->cap(3);\r
+        res = begLine + evalString(s) + endLine + '\n';\r
+        nbAt --;\r
+      }\r
+    }\r
+    for(int i = 0; i < line.size(); i++) {\r
+      if(rxValue->indexIn(line)) {\r
+        begLine = rxValue->cap(1);\r
+        s = rxValue->cap(2);\r
+        endLine = rxValue->cap(3);\r
+        res = begLine + evalValue(s) + endLine + '\n';\r
+        nbAt --;\r
+      }\r
+    }\r
+    for(int i = 0; i < line.size(); i++) {\r
+      if(rxExpr->indexIn(line)) {\r
+        expr = rxExpr->cap(1);\r
+        if(expr.count('@') == 0) {\r
+          evaluator->setExpression(expr);\r
+          s = QString::number(evaluator->evaluate());\r
+        }\r
+        res = begLine + s + endLine + '\n';\r
+        nbAt --;\r
+      }\r
+    }\r
+  }\r
+  return res;\r
+}\r
+\r
+QString BlockImplementation::evalComplex(QString line, int id) {\r
+  QString res, s, begLine, endLine, expr;\r
+  QRegExp *rxString = new QRegExp("(.*)@{(.*)}(.*)");\r
+  QRegExp *rxValue = new QRegExp("(.*)@val{(.*)}(.*)");\r
+  QRegExp *rxExpr = new QRegExp(".*@eval{(.*)}.*");\r
+  QRegExp *rxFor = new QRegExp("@foreach{.*}(@{.*})(.*)@endforeach");\r
+  QRegExp *rxCase = new QRegExp("@caseeach{.*,(.*),(.*)}(@{.*})(.*)@endcaseeach");\r
+  QRegExp *rxCaseDown = new QRegExp("@#-:(.*)");\r
+  QRegExp *rxCaseUp = new QRegExp("@#:(.*)");\r
+  evaluator->setExpression(line);\r
+\r
+  int nbAt = line.count('@') - 2;\r
+  while(nbAt != 0) {\r
+    for(int i = 0; i < line.size(); i++) {\r
+      if(rxString->indexIn(line)) {\r
+        begLine = rxString->cap(1);\r
+        s = rxString->cap(2);\r
+        endLine = rxString->cap(3);\r
+        if(evalStringComplex(s)->size() == 0)\r
+          line = begLine + evalString(s) + endLine;\r
+        nbAt --;\r
+      }\r
+    }\r
+    for(int i = 0; i < line.size(); i++) {\r
+      if(rxValue->indexIn(line)) {\r
+        begLine = rxValue->cap(1);\r
+        s = rxValue->cap(2);\r
+        endLine = rxValue->cap(3);\r
+        line = begLine + evalValue(s) + endLine;\r
+        nbAt --;\r
+      }\r
+    }\r
+    for(int i = 0; i < line.size(); i++) {\r
+      if(rxExpr->indexIn(line)) {\r
+        expr = rxExpr->cap(1);\r
+        if(expr.count('@') == 0) {\r
+          evaluator->setExpression(expr);\r
+          s = QString::number(evaluator->evaluate());\r
+        }\r
+        res = begLine + s + endLine + '\n';\r
+        nbAt --;\r
+      }\r
+    }\r
+  }\r
+\r
+  if(id == 1) {\r
+    if(rxFor->indexIn(line)) {\r
+      QString intName, instruc;\r
+      intName = rxFor->cap(1);\r
+      instruc = rxFor->cap(2);\r
+      QList<AbstractInterface*> *intList = evalStringComplex(intName);\r
+      if(intList->size() != 0) {\r
+        for(int i = 0; i < intList->size(); i++) {\r
+          res = intList->at(i)->getName() + instruc + '\n';\r
+        }\r
+      }\r
+    }\r
+  }\r
+\r
+  else if(id == 2) {\r
+    if(rxCase->indexIn(line)) {\r
+      QString intName, sigName, cases, instruc;\r
+      int number;\r
+      sigName = rxCase->cap(1);\r
+      cases = rxCase->cap(2);\r
+      intName = rxCase->cap(3);\r
+      instruc = rxCase->cap(4);\r
+      QList<AbstractInterface*> *intList = evalStringComplex(intName);\r
+      int listSize = intList->count();\r
+      res = "case " + sigName + " is\n";\r
+      if(rxCaseUp->indexIn(cases)) {\r
+        number = rxCaseUp->cap(1).toInt();\r
+        for(int j = number; j < listSize; j++) {\r
+          if(listSize > 0) {\r
+            for(int i = 0; i < listSize; i++) {\r
+              res += "\twhen " + QString::number(number) + " " + intList->at(i)->getName() + instruc + "\n";\r
+            }\r
+          }\r
+          else\r
+            res += "\twhen " + number + ' ' + intName + instruc + "\n";\r
+          number++;\r
+        }\r
+      }\r
+      if(rxCaseDown->indexIn(cases)) {\r
+        number = rxCaseDown->cap(1).toInt();\r
+        for(int j = number; j < listSize; j++) {\r
+          if(listSize > 0) {\r
+            for(int i = 0; i < listSize; i++) {\r
+              res += "\twhen " + QString::number(number) + " " + intList->at(i)->getName() + instruc + "\n";\r
+            }\r
+          }\r
+          else\r
+            res += "\twhen " + number + ' ' + intName + instruc + "\n";\r
+          number--;\r
+        }\r
+        res += "end case ;\n";\r
+      }\r
+    }\r
+  }\r
+  return res;\r
+}\r
+\r
+QString BlockImplementation::evalString(QString s) {\r
+\r
+  QString name = getIfaceUserName(block->AbstractBlock::getIfaceFromName(s));\r
+  return name;\r
+}\r
+\r
+QList<AbstractInterface*>* BlockImplementation::evalStringComplex(QString s) {\r
+\r
+  int j = 0;\r
+  QList<AbstractInterface*> *listInterfaces = new QList<AbstractInterface*>();\r
+  AbstractInterface *inter = block->AbstractBlock::getIfaceFromName(s);\r
+  QList<AbstractInterface*> listIntBlock = block->getInterfaces();\r
+  for(int i = 0; i < listIntBlock.size(); i++) {\r
+    if(inter->getName().compare(listIntBlock.at(i)->getName()) < -1) {\r
+      listInterfaces->insert(j, inter);\r
+      j ++;\r
+    }\r
+  }\r
+  return listInterfaces;\r
+}\r
+\r
+QString BlockImplementation::evalValue(QString s) {\r
+\r
+  QString val = "";\r
+  if(paramMap.contains(s))\r
+    val = paramMap.value(s);\r
+  return val;\r
+}\r
+\r
+QString BlockImplementation::getIfaceUserName(AbstractInterface* refIface) {\r
+\r
+  if (! refIface->isReferenceInterface()) return "";\r
+\r
+  AbstractInterface* funcIface = NULL;\r
+\r
+  if (refIface->getDirection() == AbstractInterface::Input) {\r
+    foreach(AbstractInterface* iface, block->getInputs()) {\r
+      FunctionalInterface* fi = (FunctionalInterface*)iface;\r
+      if (fi->getReference() == refIface) {\r
+        funcIface = iface;\r
+        break;\r
+      }\r
+    }\r
+  }\r
+  else if (refIface->getDirection() == AbstractInterface::Output) {\r
+    foreach(AbstractInterface* iface, block->getOutputs()) {\r
+      FunctionalInterface* fi = (FunctionalInterface*)iface;\r
+      if (fi->getReference() == refIface) {\r
+        funcIface = iface;\r
+        break;\r
+      }\r
+    }\r
+  }\r
+  else if (refIface->getDirection() == AbstractInterface::InOut) {\r
+    foreach(AbstractInterface* iface, block->getBidirs()) {\r
+      FunctionalInterface* fi = (FunctionalInterface*)iface;\r
+      if (fi->getReference() == refIface) {\r
+        funcIface = iface;\r
+        break;\r
+      }\r
+    }\r
+  }\r
+  if (funcIface == NULL) return "";\r
+\r
+  return funcIface->getName();\r
+}\r
+\r
+QDataStream& operator<<(QDataStream &out, const BlockImplementation &impl) {\r
+\r
+  out.setVersion(QDataStream::Qt_5_0);\r
+\r
+  QByteArray blockData;\r
+  QDataStream toWrite(&blockData, QIODevice::WriteOnly);\r
+\r
+  toWrite << impl.xmlFile;\r
+  toWrite << impl.referenceXml;\r
+  toWrite << impl.referenceMd5;\r
+\r
+  out << blockData;\r
+\r
+  return out;\r
+}\r
+\r
+QDataStream& operator>>(QDataStream &in, BlockImplementation &impl) {\r
+\r
+  quint32 blockSize;\r
+\r
+  in.setVersion(QDataStream::Qt_5_0);\r
+\r
+  in >> blockSize;\r
+\r
+  in >> impl.xmlFile;\r
+  in >> impl.referenceXml;\r
+  in >> impl.referenceMd5;\r
+\r
+  return in;\r
+}\r
+\r
+QString BlockImplementation::calculateWidth(QString s){\r
+  QRegExp *rxWidth = new QRegExp("$*([a-zA-Z0-9_-]*)");\r
+  QStringList matchList = s.split(" ");\r
+  int pos = 0;\r
+  QString res, line;\r
+  QList<BlockParameter*> listParams = reference->getParameters();\r
+\r
+  while ((pos = rxWidth->indexIn(s, pos)) != -1) {\r
+    matchList << rxWidth->cap(1);\r
+    pos += rxWidth->matchedLength();\r
+  }\r
+\r
+  for (int i = 0; i < matchList.size(); i++) {\r
+    QString match = matchList.at(i);\r
+    if(rxWidth->indexIn(match)) {\r
+      for(int j = 0; j < listParams.size(); j++) {\r
+        if(match.compare(listParams.at(j)->getName())) {\r
+          BlockParameter *param = listParams.at(i);\r
+          if(param->getContext() == "generic") {\r
+            match = match.remove('$');\r
+          }\r
+          else {\r
+            match = param->getValue().toString();\r
+          }\r
+        }\r
+      }\r
+    }\r
+  }\r
+  line = matchList.join(' ');\r
+  evaluator->setExpression(line);\r
+  res = evaluator->evaluate();\r
+  return res;\r
+}\r
+\r
diff --git a/BlockImplementation.h b/BlockImplementation.h
new file mode 100644 (file)
index 0000000..df0e499
--- /dev/null
@@ -0,0 +1,68 @@
+#ifndef __BLOCKIMPLEMENTATION_H__\r
+#define __BLOCKIMPLEMENTATION_H__\r
+\r
+#include <iostream>\r
+#include <fstream>\r
+\r
+#include <QtCore>\r
+#include <QtXml>\r
+\r
+class ReferenceBlock;\r
+class FunctionalBlock;\r
+class AbstractInterface;\r
+\r
+#include "ArithmeticEvaluator.h"\r
+class ArithmeticEvaluator;\r
+\r
+#include "Exception.h"\r
+class Exception;\r
+\r
+\r
+using namespace std;\r
+using namespace Qt;\r
+\r
+class BlockImplementation {\r
+\r
+public:\r
+\r
+  BlockImplementation(const QString& _xmlFile);\r
+  BlockImplementation(const QString& _xmlFile, const QString& _referenceXml, const QString& _referenceMd5);\r
+\r
+  inline QString getXmlFile() { return xmlFile; }\r
+  inline QString getReferenceXml() { return referenceXml; }\r
+  inline QString getReferenceMd5() { return referenceMd5; }\r
+  QString eval(QString line, QTextStream& out);\r
+  QString evalComplex(QString line, int num);\r
+  QString evalString(QString s);\r
+  QList<AbstractInterface*>* evalStringComplex(QString s);\r
+  QString evalValue(QString s);\r
+  QString calculateWidth(QString s);\r
+\r
+  inline void setReference(ReferenceBlock* _reference) { reference = _reference; }\r
+\r
+  void generateVHDL(FunctionalBlock* _block, const QString& path) throw(Exception); // main entry to generate the VHDL code\r
+\r
+private:  \r
+  QString xmlFile;\r
+  QString referenceXml;\r
+  QString referenceMd5;\r
+  QString nameEnt, line;\r
+  QMap<QString, int> paramMap;\r
+  ArithmeticEvaluator* evaluator;\r
+  ReferenceBlock* reference;\r
+  FunctionalBlock* block; // the current functional block for which this implementation is used.\r
+\r
+  void generateComments(QDomElement &elt,QString coreFile, QTextStream& out) throw(Exception); // generates comments from <comments> element\r
+  void generateLibraries(QDomElement &elt, QTextStream& out) throw(Exception); // generates libraries from <libraries> element\r
+  void generateEntity(QTextStream& out, bool hasController=false) throw(Exception); // generate the entity using reference\r
+  void generateArchitecture(QDomElement &elt, QTextStream& out) throw(Exception); // generate the architecture using <architecture> element\r
+  void generateController(QTextStream& out) throw(Exception); // generate the wishbone controller of the block\r
+\r
+  QString getIfaceUserName(AbstractInterface* refIface); // get the name of an interface given by the user, from the reference interface\r
+\r
+  friend QDataStream &operator<<(QDataStream &out, const BlockImplementation &impl);\r
+  friend QDataStream &operator>>(QDataStream &in, BlockImplementation &impl);\r
+};\r
+\r
+#endif // __BLOCKIMPLEMENTATION_H__\r
+\r
diff --git a/BlockLibraryTree.cpp b/BlockLibraryTree.cpp
new file mode 100644 (file)
index 0000000..33980f9
--- /dev/null
@@ -0,0 +1,137 @@
+#include "BlockLibraryTree.h"
+
+BlockLibraryTree::BlockLibraryTree() {
+  tabCategories = NULL;
+  tabIdParent = NULL;
+  nbCategories = 0;
+}
+
+BlockLibraryTree::~BlockLibraryTree() {
+  clear();
+}
+
+void BlockLibraryTree::clear() {
+
+  for(int i=0;i<nbCategories;i++) {
+    delete tabCategories[i];
+  }
+  delete [] tabCategories;
+  nbCategories = 0;
+}
+
+void BlockLibraryTree::clearBlocks() {
+
+  for(int i=0;i<nbCategories;i++) {
+    tabCategories[i]->blocks.clear();
+  }
+}
+
+void BlockLibraryTree::addItem(QXmlAttributes &attributes)
+{
+  nbCategories++;
+  if(tabCategories == NULL){
+    tabCategories = new BlockCategory* [1];
+    tabIdParent = new int[1];
+  }
+  else{
+    BlockCategory** tmpTabCat = new BlockCategory* [nbCategories];
+    int* tmpTabParent = new int[nbCategories];
+    for(int i=0; i< nbCategories; i++){
+      tmpTabCat[i] = tabCategories[i];
+      tmpTabParent[i] = tabIdParent[i];
+    }
+    tabCategories = tmpTabCat;
+    tabIdParent = tmpTabParent;
+  }
+
+  QString name = attributes.value(0);
+  int id = attributes.value(1).toInt();
+  int idParent = attributes.value(2).toInt();
+  BlockCategory* cat = new BlockCategory(name,id);
+  tabCategories[id] = cat;
+  tabIdParent[id] = idParent;
+}
+
+bool BlockLibraryTree::initChildParent()
+{
+  // initializing parent/childs
+  for(int i=0;i<nbCategories;i++) {
+    if (tabIdParent[i] != -1) {
+      if (tabIdParent[i] >= nbCategories) return false;
+      tabCategories[i]->setParent(tabCategories[tabIdParent[i]]);
+      tabCategories[tabIdParent[i]]->addChild(tabCategories[i]);
+    }
+  }
+  return true;
+}
+
+
+QDomElement BlockLibraryTree::save(QDomDocument &doc) {
+
+}
+
+/* NOTE : load() is the only way to initialize the tree.
+   It is done at the begining of the application, while reading
+   the configuration file.
+   elt MUST be the DOM element that corresponds to the tag <categories>
+ */
+void BlockLibraryTree::load(QDomElement &elt) throw(Exception) {
+
+  if (elt.tagName() != "categories") throw(Exception(CONFIGFILE_CORRUPTED));
+
+  QString nbStr = elt.attribute("nb","none");
+  bool ok;
+  int nb = nbStr.toInt(&ok);
+  QDomNodeList list = elt.elementsByTagName("category");
+  nbCategories = list.size();
+  if (nb != nbCategories) throw(Exception(CONFIGFILE_CORRUPTED));
+  QString name;
+  int id;
+  QString idStr;
+  int idParent;
+  QString idParentStr;
+
+  tabCategories = new BlockCategory* [nbCategories];
+  tabIdParent = new int[nbCategories];
+  BlockCategory* cat = NULL;
+
+  // creating all BlockCategory objects
+  for(int i=0;i<nbCategories;i++) {
+    QDomNode node = list.item(i);
+    QDomElement e = node.toElement();
+    name = e.attribute("name","none");
+    idStr = e.attribute("id","none");
+    idParentStr = e.attribute("parent","none");
+    id = idStr.toInt(&ok);
+    if ((!ok) || (id < 0) || (id >= nbCategories)) throw(Exception(CONFIGFILE_CORRUPTED));
+    idParent = idParentStr.toInt(&ok);
+    if ((!ok)|| (idParent < -1) || (idParent >= nbCategories)) throw(Exception(CONFIGFILE_CORRUPTED));
+    cat = new BlockCategory(name,id);
+    tabCategories[id] = cat;
+    tabIdParent[id] = idParent;
+  }
+
+  ok = initChildParent();
+  delete [] tabIdParent;
+  if (!ok) throw(Exception(CONFIGFILE_CORRUPTED));
+}
+
+BlockCategory* BlockLibraryTree::searchCategory(int id) {
+
+  if (tabCategories != NULL) {
+    if ((id>=0) && (id < nbCategories)) {
+      return tabCategories[id];
+    }
+  }
+
+  return NULL;
+}
+
+BlockCategory *BlockLibraryTree::getRoot() {
+  if (tabCategories != NULL) {
+    if (nbCategories > 0) {
+      return tabCategories[0];
+    }
+  }
+  return NULL;
+}
diff --git a/BlockLibraryTree.h b/BlockLibraryTree.h
new file mode 100644 (file)
index 0000000..f8fa60c
--- /dev/null
@@ -0,0 +1,50 @@
+#ifndef __BLOCKLIBRARYTREE_H__
+#define __BLOCKLIBRARYTREE_H__
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <signal.h>
+
+#include <iostream>
+#include <fstream>
+
+#include <QtCore>
+
+#include "BlockCategory.h"
+#include "Exception.h"
+
+using namespace std;
+using namespace Qt;
+class BlockCategory;
+class BlockLibraryTree {
+
+public :
+  BlockLibraryTree();
+  ~BlockLibraryTree();
+
+  void clear(); // free thewhole tree
+  void clearBlocks(); // just remove the blocks from the BlockCateogry lists
+  void addItem(QXmlAttributes &attributes);
+  bool initChildParent();
+
+  BlockCategory *getRoot();
+  BlockCategory *searchCategory(int id);
+
+  QDomElement save(QDomDocument &doc);
+  void load(QDomElement &elt) throw(Exception);
+private:
+  /* NOTE :
+     This class builds a tree of BlockCategory, but it also stores all BlockCategory object
+     in an array so that access via an id is direct.
+
+     The root of the tree is in fact tabCategories[0]
+   */
+  BlockCategory** tabCategories;
+  int* tabIdParent;
+  int nbCategories;
+
+};
+
+
+#endif // BLOCKLIBRARYTREE_H
diff --git a/BlockLibraryWidget.cpp b/BlockLibraryWidget.cpp
new file mode 100644 (file)
index 0000000..0aa9ed1
--- /dev/null
@@ -0,0 +1,107 @@
+#include "BlockLibraryWidget.h"
+#include "BlockLibraryTree.h"
+
+BlockLibraryWidget::BlockLibraryWidget(Dispatcher* _dispatcher,
+                                       Parameters* _params,
+                                       QWidget *parent) : QWidget(parent) {
+
+
+  dispatcher = _dispatcher;
+  params = _params;
+
+  // creating the widget : tree, buttons, ...
+  layout = new QBoxLayout(QBoxLayout::TopToBottom, this);
+  tree = new QTreeWidget(this);
+  buttonAdd = new QPushButton("add", this);
+  buttonAdd->setEnabled(false);
+
+  connect(tree, SIGNAL(itemClicked(QTreeWidgetItem*,int)), this, SLOT(clicked()));
+  connect(tree, SIGNAL(itemDoubleClicked(QTreeWidgetItem*,int)), this, SLOT(doubleClicked()));
+  connect(buttonAdd, SIGNAL(clicked()), this, SLOT(addClicked()));
+
+  BlockCategory* cat = params->categoryTree->searchCategory(0);
+
+  QTreeWidgetItem* item = tree->invisibleRootItem();
+  tree->setHeaderLabel("Blocks list");
+
+
+  addChild(cat,item);
+
+  layout->addWidget(tree);
+  layout->addWidget(buttonAdd);
+  this->setLayout(layout);
+
+  this->setFixedSize(300,230);
+}
+
+
+BlockLibraryWidget::~BlockLibraryWidget() {
+}
+
+void BlockLibraryWidget::addChild(BlockCategory *catParent,QTreeWidgetItem* itemParent) {
+
+  QTreeWidgetItem* newItemCat = NULL;
+  QTreeWidgetItem* newItemBlock = NULL;
+
+  QList<BlockCategory *> childs = catParent->getAllChilds();
+  foreach(BlockCategory* cat, childs){
+    newItemCat = new QTreeWidgetItem(itemParent);
+    newItemCat->setData(0,Qt::DisplayRole, cat->getName());
+    QList<ReferenceBlock*> list = cat->getBlocks();
+    for(int i=0; i<list.length(); i++){
+      newItemBlock = new QTreeWidgetItem(newItemCat);
+      newItemBlock->setData(0,Qt::DisplayRole, list.at(i)->getName());
+      newItemBlock->setData(1,Qt::DisplayRole, cat->getId());
+      newItemBlock->setData(2,Qt::DisplayRole, i);
+      newItemBlock->setIcon(0,QIcon("icons/window_new.png"));
+    }
+    addChild(cat,newItemCat);
+  }
+  /* TO DO :
+     - getting the childs of catParent
+     - for each BlockCategory cat of that list :
+        - create an new TreeWidgetItem (newImteCat), with itemParent as a parent
+        - set the first column of that item with the categry name
+        - get the list of the blocks that are associated with cat
+        - for i = 0 to that list size.
+           - create a new TreeWidgetItem (newItemBlock), with newItemCat as a parent
+           - set the first column of that item with the block name
+           - set the second column of that item with the newItemCat id
+           - set the third column of that item with the value of i
+        - endfor
+        - call again addChild with cat and newImteCat as parameters
+      - end for
+  */
+}
+
+
+void BlockLibraryWidget::addClicked() {
+
+  QTreeWidgetItem *item = tree->selectedItems().at(0);
+  if(item->data(1,Qt::DisplayRole).isValid() && item->data(2,Qt::DisplayRole).isValid()){
+    int idParent = item->data(1,Qt::DisplayRole).toInt();
+    int idBlock = item->data(2,Qt::DisplayRole).toInt();
+    dispatcher->addBlock(idParent, idBlock);
+  }
+
+  // only take the first selected
+  // retrieve id of category and id of block
+  // calling dispatcher addBlock() method.
+}
+
+
+void BlockLibraryWidget::clicked()
+{
+  if(tree->selectedItems().length() > 0){
+    QTreeWidgetItem *item = tree->selectedItems().at(0);
+    if(item->data(1,Qt::DisplayRole).isValid())
+      buttonAdd->setEnabled(true);
+    else
+      buttonAdd->setEnabled(false);
+  }
+}
+
+void BlockLibraryWidget::doubleClicked()
+{
+  addClicked();
+}
diff --git a/BlockLibraryWidget.h b/BlockLibraryWidget.h
new file mode 100644 (file)
index 0000000..f07be4d
--- /dev/null
@@ -0,0 +1,45 @@
+#ifndef __BLOCKLIBRARYWIDGET_H__
+#define __BLOCKLIBRARYWIDGET_H__
+
+#include <iostream>
+
+#include <QtCore>
+#include <QtGui>
+
+#include "Dispatcher.h"
+class Dispatcher;
+#include "Parameters.h"
+class Parameters;
+#include "BlockCategory.h"
+class BlockCategory;
+
+using namespace std;
+using namespace Qt;
+
+class BlockLibraryWidget : public QWidget {
+  Q_OBJECT
+
+public:
+  explicit BlockLibraryWidget(Dispatcher* _dispatcher, Parameters* _params, QWidget *parent = 0);
+  ~BlockLibraryWidget();
+
+private slots:
+    void addClicked();
+    void clicked();
+    void doubleClicked();
+
+
+private:
+  Parameters* params;
+  Dispatcher* dispatcher;
+  QTreeWidget* tree;
+  QPushButton* buttonAdd;
+  QBoxLayout *layout;
+  // other attributes
+  
+  void addChild(BlockCategory *catParent, QTreeWidgetItem* itemParent);
+  void addButtons();
+
+};
+
+#endif // __BLOCKLIBRARYWIDGET_H__
diff --git a/BlockParameter.cpp b/BlockParameter.cpp
new file mode 100644 (file)
index 0000000..f8dfcd7
--- /dev/null
@@ -0,0 +1,121 @@
+#include "BlockParameter.h"\r
+\r
+BlockParameter::BlockParameter() {\r
+  owner = NULL;\r
+  name = "";  \r
+  type = BlockParameter::String;\r
+  defaultValue = QVariant();\r
+}\r
+\r
+BlockParameter::BlockParameter(AbstractBlock* _owner, const QString &_name, const QString &_type, const QString &_value) {\r
+  owner = _owner;\r
+  name =_name;  \r
+  type = typeFromString(_type);\r
+  defaultValue = QVariant(_value);\r
+}\r
+\r
+BlockParameter::~BlockParameter(){\r
+\r
+}\r
+\r
+QVariant BlockParameter::getValue() {\r
+  return defaultValue;\r
+}\r
+\r
+bool BlockParameter::isUserParameter() {\r
+  return false;\r
+\r
+}\r
+\r
+bool BlockParameter::isGenericParameter() {\r
+  return false;\r
+}\r
+\r
+bool BlockParameter::isWishboneParameter() {\r
+  return false;\r
+}\r
+\r
+bool BlockParameter::isPortParameter() {\r
+  return false;\r
+}\r
+\r
+void BlockParameter::setValue(const QString& _value) {\r
+  defaultValue = QVariant(_value);\r
+}\r
+\r
+bool BlockParameter::isValueSet() {\r
+  if (defaultValue.isNull()) return false;\r
+  return true;\r
+}\r
+                     \r
+QString BlockParameter::toVHDL(int context, int flags) {\r
+\r
+  QString ret="";  \r
+  return ret;\r
+}\r
+\r
+QString BlockParameter::getTypeString() {\r
+  if (type == BlockParameter::Bit) {\r
+    return "bit";\r
+  }\r
+  else if (type == BlockParameter::BitVector) {\r
+    return "bit_vector";\r
+  }\r
+  else if (type == BlockParameter::Boolean) {\r
+    return "boolean";\r
+  }\r
+  else if (type == BlockParameter::Integer) {\r
+    return "integer";\r
+  }\r
+  else if (type == BlockParameter::Natural) {\r
+    return "natural";\r
+  }\r
+  else if (type == BlockParameter::Positive) {\r
+    return "positive";\r
+  }\r
+  else if (type == BlockParameter::Real) {\r
+    return "real";\r
+  }\r
+  else if (type == BlockParameter::Character) {\r
+    return "character";\r
+  }\r
+  else if (type == BlockParameter::String) {\r
+    return "string";\r
+  }\r
+  else if (type == BlockParameter::Time) {\r
+    return "time";\r
+  }\r
+  return "undefined";\r
+}\r
+\r
+int BlockParameter::typeFromString(const QString &_type) {\r
+  int ret = BlockParameter::Expression;\r
+\r
+  if (_type == "string") {\r
+    ret = BlockParameter::String;\r
+  }\r
+  else if (_type == "expression") {\r
+    ret = BlockParameter::Expression;\r
+  }\r
+  else if (_type == "boolean") {\r
+    ret = BlockParameter::Boolean;\r
+  }\r
+  else if (_type == "integer") {\r
+    ret = BlockParameter::Integer;\r
+  }\r
+  else if (_type == "natural") {\r
+    ret = BlockParameter::Natural;\r
+  }\r
+  else if (_type == "positive") {\r
+    ret = BlockParameter::Positive;\r
+  }\r
+  else if (_type == "real") {\r
+    ret = BlockParameter::Real;\r
+  }\r
+  else if (_type == "time") {\r
+    ret = BlockParameter::Time;\r
+  }\r
+  return ret;\r
+}\r
+\r
+\r
diff --git a/BlockParameter.h b/BlockParameter.h
new file mode 100644 (file)
index 0000000..e0c4af2
--- /dev/null
@@ -0,0 +1,68 @@
+#ifndef __BLOCKPARAMETER_H__\r
+#define __BLOCKPARAMETER_H__\r
+\r
+#include <iostream>\r
+#include <fstream>\r
+\r
+#include <QtCore>\r
+\r
+#include "AbstractBlock.h"\r
+class AbstractBlock;\r
+\r
+using namespace std;\r
+using namespace Qt;\r
+\r
+\r
+class BlockParameter {\r
+\r
+public :\r
+\r
+  enum ParamType { Expression = 1, Character, String, Bit, BitVector, Boolean, Integer, Natural, Positive, Real, Time};\r
+  // a bit ugly to put that here but more practical for using them\r
+  enum ParamWBAccess { Read = 1, Write = 2};\r
+  enum ParamWBDuration { Permanent = 1, Trigger = 2 };\r
+  enum ParamVHDLContext { Entity = 1, Component = 2, Architecture = 3 }; // NB : 3 is when creating an instance of the block that owns this iface\r
+  enum ParamVHDLFlags { NoComma = 1 };\r
+\r
+  BlockParameter();\r
+  BlockParameter(AbstractBlock* _owner, const QString& _name , const QString& _type, const QString& _value);\r
+\r
+  virtual ~BlockParameter();\r
+\r
+  // getters\r
+  inline AbstractBlock* getOwner() { return owner; }\r
+  inline QString getName() { return name; }\r
+  inline int getType() { return type; }\r
+  QString getTypeString();\r
+  virtual QVariant getValue(); // may be overriden\r
+  virtual QString getContext() = 0;\r
+\r
+  // setters\r
+  inline void setOwner(AbstractBlock* _owner) { owner = _owner; }\r
+  inline void setName(const QString& _name) { name = _name; }\r
+  inline void setType(int _type) { type = _type; }\r
+  virtual void setValue(const QString& _value);\r
+\r
+  // testers\r
+  virtual bool isValueSet(); // may be overridden for User and Generic parameters\r
+  virtual bool isUserParameter();\r
+  virtual bool isGenericParameter();\r
+  virtual bool isWishboneParameter();\r
+  virtual bool isPortParameter();\r
+\r
+  // others\r
+  virtual BlockParameter* clone() = 0;\r
+  virtual QString toVHDL(int context, int flags);\r
+  int typeFromString(const QString& _type);\r
+\r
+protected:\r
+\r
+  AbstractBlock* owner;\r
+  QString name;  \r
+  int type;\r
+  QVariant defaultValue; // the value set during construction\r
+\r
+};\r
+\r
+#endif // __BLOCKPARAMETER_H__\r
+\r
diff --git a/BlockParameterGeneric.cpp b/BlockParameterGeneric.cpp
new file mode 100644 (file)
index 0000000..5b15eb9
--- /dev/null
@@ -0,0 +1,97 @@
+#include "BlockParameterGeneric.h"\r
+#include "GroupBlock.h"\r
+#include "FunctionalBlock.h"\r
+\r
+BlockParameterGeneric::BlockParameterGeneric() : BlockParameter() {\r
+  userValue = defaultValue;\r
+}\r
+\r
+BlockParameterGeneric::BlockParameterGeneric(AbstractBlock* _owner, const QString &_name, const QString &_type, const QString &_value) : BlockParameter(_owner, _name, _type, _value) {\r
+  userValue = defaultValue;\r
+}\r
+\r
+QVariant BlockParameterGeneric::getValue() {\r
+  if (isValueSet()) {\r
+    return userValue;\r
+  }\r
+  return defaultValue;\r
+}\r
+\r
+bool BlockParameterGeneric::isGenericParameter() {\r
+  return true;\r
+}\r
+\r
+void BlockParameterGeneric::setValue(const QString& _value) {\r
+  userValue = QVariant(_value);\r
+}\r
+\r
+\r
+bool BlockParameterGeneric::isValueSet() {\r
+  if (userValue.isNull()) return false;\r
+  return true;\r
+}\r
+\r
+bool BlockParameterGeneric::isDefaultValue() {\r
+  if (userValue == defaultValue) return true;\r
+  return false;\r
+}\r
+\r
+BlockParameter* BlockParameterGeneric::clone() {  \r
+\r
+  BlockParameter* block = new BlockParameterGeneric(owner,name,getTypeString(),defaultValue.toString());\r
+  return block;\r
+}\r
+\r
+QString BlockParameterGeneric::toVHDL(int context, int flags) {\r
+\r
+  QString ret="";\r
+\r
+\r
+  if ((context == BlockParameter::Entity) || (context == BlockParameter::Component)) {\r
+\r
+    QString formatValue = "%1 : %2 := %3";\r
+    QString formatNoValue = "%1 : %2";\r
+    if ((flags & BlockParameter::NoComma) == 0) {\r
+      formatValue.append(";");\r
+      formatNoValue.append(";");\r
+    }\r
+\r
+    if (!userValue.isNull()) {\r
+      ret = formatValue.arg(name).arg(type).arg(userValue.toString());\r
+    }\r
+    else if (!defaultValue.isNull()) {\r
+      ret = formatValue.arg(name).arg(type).arg(defaultValue.toString());\r
+    }\r
+    else {\r
+      ret = formatNoValue.arg(name).arg(type);\r
+    }\r
+  }\r
+  else if (context == BlockParameter::Architecture) {\r
+    QString format = "%1 => %2";\r
+    if ((flags & BlockParameter::NoComma) == 0) {\r
+      format.append(";");\r
+    }\r
+    AbstractBlock* parent = owner->getParent();\r
+    BlockParameter* p = parent->getParameterFromName(name);\r
+    if (p != NULL) {\r
+      /* the parent group has a generic parameter with the same\r
+           name\r
+        */\r
+      ret = format.arg(name).arg(name);\r
+    }\r
+    else {\r
+      if (!userValue.isNull()) {\r
+        ret = format.arg(name).arg(userValue.toString());\r
+      }\r
+      else if (!defaultValue.isNull()) {\r
+        ret = format.arg(name).arg(defaultValue.toString());\r
+      }\r
+      else {\r
+        // abnormal case\r
+        ret = format.arg(name).arg("INVALID_VALUE");\r
+      }\r
+    }\r
+  }\r
+  return ret;\r
+}\r
+\r
diff --git a/BlockParameterGeneric.h b/BlockParameterGeneric.h
new file mode 100644 (file)
index 0000000..9fb81a6
--- /dev/null
@@ -0,0 +1,46 @@
+#ifndef __BLOCKPARAMETERGENERIC_H__\r
+#define __BLOCKPARAMETERGENERIC_H__\r
+\r
+#include <iostream>\r
+#include <fstream>\r
+\r
+#include <QtCore>\r
+\r
+#include "BlockParameter.h"\r
+class BlockParameter;\r
+\r
+using namespace std;\r
+using namespace Qt;\r
+\r
+\r
+class BlockParameterGeneric : public BlockParameter {\r
+\r
+public :  \r
+\r
+  BlockParameterGeneric();\r
+  BlockParameterGeneric(AbstractBlock* _owner, const QString& _name, const QString& _type, const QString& _value);\r
+\r
+  // getters\r
+  QVariant getValue();\r
+  inline QString getContext() { return "generic";}\r
+  // setters\r
+  void setValue(const QString& _value);\r
+  inline void resetToDefaultValue() { userValue = defaultValue; }\r
+\r
+  // testers\r
+  bool isValueSet();\r
+  bool isDefaultValue();\r
+  bool isGenericParameter();\r
+\r
+  // others\r
+  BlockParameter* clone();\r
+  QString toVHDL(int context, int flags);\r
+\r
+private:\r
+\r
+  QVariant userValue;\r
+\r
+};\r
+\r
+#endif // __BLOCKPARAMETERGENERIC_H__\r
+\r
diff --git a/BlockParameterPort.cpp b/BlockParameterPort.cpp
new file mode 100644 (file)
index 0000000..c33724b
--- /dev/null
@@ -0,0 +1,58 @@
+#include "BlockParameterPort.h"\r
+#include "ArithmeticEvaluator.h"\r
+#include "FunctionalBlock.h"\r
+#include "FunctionalInterface.h"\r
+\r
+BlockParameterPort::BlockParameterPort() : BlockParameter() {\r
+  ifaceName = "";\r
+}\r
+\r
+BlockParameterPort::BlockParameterPort(AbstractBlock* _owner, const QString &_name, const QString &_value, const QString &_ifaceName) : BlockParameter(_owner, _name, "expression", _value) {\r
+  ifaceName = _ifaceName;\r
+}\r
+\r
+bool BlockParameterPort::isPortParameter() {\r
+  return true;\r
+}\r
+\r
+BlockParameter* BlockParameterPort::clone() {\r
+  BlockParameter* block = new BlockParameterPort(owner,name,defaultValue.toString(),ifaceName);\r
+  return block;\r
+}\r
+\r
+QString BlockParameterPort::toVHDL(int context, int flags) {\r
+  QString expr="";\r
+  QString ret="";\r
+  ArithmeticEvaluator evaluator;\r
+\r
+  if (!defaultValue.isNull()) {\r
+    expr = defaultValue.toString();\r
+    try {\r
+      evaluator.setVariableMarkers("$");\r
+      evaluator.setExpression(expr);\r
+\r
+      double ifaceNb = 0.0;\r
+      double ifaceWidth = 0.0;\r
+      FunctionalInterface* iface = (FunctionalInterface*)(owner->getIfaceFromName(ifaceName));\r
+      if (iface == NULL) return "INVALID_INTERFACE_NAME";\r
+\r
+      // must get the number of instance of\r
+      ifaceNb = iface->getInterfaceMultiplicity();\r
+\r
+      int result = 0;\r
+      evaluator.setVariableValue("$if_width",ifaceWidth);\r
+      evaluator.setVariableValue("$if_nb",ifaceNb);\r
+      result = (int)(evaluator.evaluate());\r
+      ret.setNum(result);\r
+    }\r
+    catch(int e) {\r
+      cerr << "invalid expression in port parameter " << qPrintable(name) << " at character " << e << endl;\r
+    }\r
+  }\r
+\r
+  return ret;\r
+}\r
+\r
+void BlockParameterPort::setIfaceName(const QString& _ifaceName) {\r
+  ifaceName = _ifaceName;\r
+}\r
diff --git a/BlockParameterPort.h b/BlockParameterPort.h
new file mode 100644 (file)
index 0000000..3050a1b
--- /dev/null
@@ -0,0 +1,42 @@
+#ifndef __BLOCKPARAMETERPORT_H__\r
+#define __BLOCKPARAMETERPORT_H__\r
+\r
+#include <iostream>\r
+#include <fstream>\r
+\r
+#include <QtCore>\r
+\r
+#include "BlockParameter.h"\r
+class BlockParameter;\r
+\r
+using namespace std;\r
+using namespace Qt;\r
+\r
+class BlockParameterPort : public BlockParameter {\r
+\r
+public :  \r
+\r
+  BlockParameterPort();\r
+  BlockParameterPort(AbstractBlock* _owner, const QString& _name, const QString& _value, const QString& _ifaceName);\r
+\r
+  // getters\r
+  inline QString getIfaceName() { return ifaceName; }\r
+  inline QString getContext() { return "port";}\r
+  // setters\r
+  void setIfaceName(const QString& _ifaceName);\r
+\r
+  // testers\r
+  bool isPortParameter();\r
+\r
+  // others\r
+  BlockParameter* clone();\r
+  QString toVHDL(int context, int flags);\r
+\r
+private:\r
+\r
+  QString ifaceName;\r
+\r
+};\r
+\r
+#endif // __BLOCKPARAMETERPORT_H__\r
+\r
diff --git a/BlockParameterUser.cpp b/BlockParameterUser.cpp
new file mode 100644 (file)
index 0000000..d0d870f
--- /dev/null
@@ -0,0 +1,56 @@
+#include "BlockParameterUser.h"\r
+\r
+BlockParameterUser::BlockParameterUser() : BlockParameter() {\r
+  userValue = defaultValue;\r
+}\r
+\r
+BlockParameterUser::BlockParameterUser(AbstractBlock* _owner, const QString &_name, const QString &_value) : BlockParameter(_owner, _name, "string", _value) {\r
+  userValue = defaultValue;\r
+}\r
+\r
+QVariant BlockParameterUser::getValue() {\r
+  if (isValueSet()) {\r
+    return userValue;\r
+  }\r
+  return defaultValue;\r
+}\r
+\r
+bool BlockParameterUser::isUserParameter() {\r
+  return true;\r
+}\r
+\r
+bool BlockParameterUser::isValueSet() {\r
+  if (userValue.isNull()) return false;\r
+  return true;\r
+}\r
+\r
+bool BlockParameterUser::isDefaultValue() {\r
+  if (userValue == defaultValue) return true;\r
+  return false;\r
+}\r
+\r
+BlockParameter* BlockParameterUser::clone() {\r
+  BlockParameter* block = new BlockParameterUser(owner,name,defaultValue.toString());\r
+  return block;\r
+}\r
+\r
+QString BlockParameterUser::toVHDL(int context, int flags) {\r
+\r
+  // NB : context and flags are purely ignored\r
+  QString ret="";\r
+  if (!userValue.isNull()) {\r
+    ret = userValue.toString();\r
+  }\r
+  if (!defaultValue.isNull()) {\r
+    ret = defaultValue.toString();\r
+  }\r
+  else {\r
+    ret = "";\r
+  }\r
+  return ret;\r
+}\r
+\r
+void BlockParameterUser::setValue(const QString& _value) {\r
+  userValue = QVariant(_value);\r
+}\r
+\r
diff --git a/BlockParameterUser.h b/BlockParameterUser.h
new file mode 100644 (file)
index 0000000..3da12a3
--- /dev/null
@@ -0,0 +1,57 @@
+#ifndef __BLOCKPARAMETERUSER_H__\r
+#define __BLOCKPARAMETERUSER_H__\r
+\r
+#include <iostream>\r
+#include <fstream>\r
+\r
+#include <QtCore>\r
+\r
+#include "BlockParameter.h"\r
+class BlockParameter;\r
+\r
+using namespace std;\r
+using namespace Qt;\r
+\r
+/* NOTES :\r
+\r
+  A BlockParameterUser represents string that will be put in the generated VHDL code\r
+  each time a @val{param_name} is encountered. The default value of the string is given\r
+  at construction. If it is empty, user will have to provide a value before VHDL generation.\r
+  If it's not empty, user can still change this value before generation.\r
+  Since this string can be almost everything, it may lead to incorrect VHDL code.\r
+  But no validity check is done !\r
+\r
+  The type of such a parameter is always "string".\r
+\r
+ */\r
+class BlockParameterUser : public BlockParameter {\r
+\r
+public :\r
+\r
+  BlockParameterUser();\r
+  BlockParameterUser(AbstractBlock* _owner, const QString& _name, const QString& _value);\r
+\r
+  // getters\r
+  QVariant getValue();\r
+  inline QString getContext() { return "user";}\r
+  // setters\r
+  void setValue(const QString& _value);\r
+  inline void resetToDefaultValue() { userValue = defaultValue; }\r
+\r
+  // testers\r
+  bool isValueSet();\r
+  bool isDefaultValue();\r
+  bool isUserParameter();\r
+\r
+  // others\r
+  BlockParameter* clone();\r
+  QString toVHDL(int context, int flags);\r
+\r
+private:\r
+\r
+  QVariant userValue;\r
+\r
+};\r
+\r
+#endif // __BLOCKPARAMETERUSER_H__\r
+\r
diff --git a/BlockParameterWishbone.cpp b/BlockParameterWishbone.cpp
new file mode 100644 (file)
index 0000000..4d13338
--- /dev/null
@@ -0,0 +1,90 @@
+#include "BlockParameterWishbone.h"\r
+\r
+BlockParameterWishbone::BlockParameterWishbone() : BlockParameter() {\r
+  userValue = defaultValue;\r
+  width = "0";\r
+  wbAccess = BlockParameter::Read;\r
+  wbValue = "0";\r
+  wbDuration = BlockParameter::Permanent;\r
+}\r
+\r
+BlockParameterWishbone::BlockParameterWishbone(AbstractBlock* _owner, const QString& _name , const QString& _type, const QString& _width, const QString& _value, int _wbAccess, QString _wbValue, int _wbDuration) : BlockParameter (_owner, _name, _type, _value) {\r
+  userValue = _value;\r
+  width = _width;\r
+  wbAccess = _wbAccess;\r
+  wbValue = _wbValue;\r
+  wbDuration = _wbDuration;\r
+}\r
+\r
+QVariant BlockParameterWishbone::getValue() {\r
+  if (isValueSet()) {\r
+    return userValue;\r
+  }\r
+  return defaultValue;\r
+}\r
+\r
+bool BlockParameterWishbone::isWishboneParameter() {\r
+  return true;\r
+}\r
+\r
+void BlockParameterWishbone::setValue(const QString& _value) {\r
+  userValue = QVariant(_value);\r
+}\r
+\r
+bool BlockParameterWishbone::isValueSet() {\r
+  if (userValue.isNull()) return false;\r
+  return true;\r
+}\r
+\r
+bool BlockParameterWishbone::isDefaultValue() {\r
+  if (userValue == defaultValue) return true;\r
+  return false;\r
+}\r
+\r
+BlockParameter* BlockParameterWishbone::clone() {\r
+  BlockParameter* block = new BlockParameterWishbone(owner,name,getTypeString(),width,defaultValue.toString(),wbAccess,wbValue,wbDuration);\r
+  return block;\r
+}\r
+\r
+QString BlockParameterWishbone::toVHDL(int context, int flags) {\r
+\r
+  QString ret="";\r
+  bool ok;\r
+  if ((context == BlockParameter::Entity) || (context == BlockParameter::Component)) {\r
+\r
+    QString formatBool = "%1 : %2 std_logic";\r
+    QString formatVector = "%1 : %2 std_logic_vector(%3 downto %4)";\r
+    if ((flags & BlockParameter::NoComma) == 0) {\r
+      formatBool.append(";");\r
+      formatVector.append(";");\r
+    }\r
+    QString orientation="";\r
+    if (wbAccess == Read) {\r
+      orientation = "out";\r
+    }\r
+    else {\r
+      orientation = "in";\r
+    }\r
+    if (type == Boolean) {\r
+      ret = formatVector.arg(name).arg(orientation);\r
+    }\r
+    else if (type == Natural) {\r
+      int w = width.toInt(&ok);\r
+      if (!ok) {\r
+        ret = formatVector.arg(name).arg(orientation).arg("INVALID SIZE").arg("0");\r
+      }\r
+      else {\r
+        w -= 1;\r
+        ret = formatVector.arg(name).arg(orientation).arg(w).arg("0");\r
+      }\r
+    }\r
+    else if (type == Expression) {\r
+      QString w = width.remove('$');\r
+      w.append("-1");\r
+      ret = formatVector.arg(name).arg(orientation).arg(w).arg("0");\r
+    }\r
+  }\r
+  return ret;\r
+}\r
+\r
+\r
diff --git a/BlockParameterWishbone.h b/BlockParameterWishbone.h
new file mode 100644 (file)
index 0000000..37be6c0
--- /dev/null
@@ -0,0 +1,58 @@
+#ifndef __BLOCKPARAMETERWISHBONE_H__\r
+#define __BLOCKPARAMETERWISHBONE_H__\r
+\r
+#include <iostream>\r
+#include <fstream>\r
+\r
+#include <QtCore>\r
+\r
+#include "BlockParameter.h"\r
+class BlockParameter;\r
+\r
+using namespace std;\r
+using namespace Qt;\r
+\r
+class BlockParameterWishbone : public BlockParameter {\r
+\r
+public :  \r
+\r
+  BlockParameterWishbone();\r
+  BlockParameterWishbone(AbstractBlock* _owner, const QString& _name , const QString& _type, const QString& _width, const QString& _value, int _wbAccess = BlockParameter::Read, QString _wbValue = QString(), int _wbDuration = BlockParameter::Permanent);\r
+\r
+  // getters\r
+  QVariant getValue();\r
+  inline QString getContext() { return "wb";}\r
+  inline QString getWidth() { return width; }\r
+  inline int getWBAccess() { return wbAccess; }\r
+  inline QString getWBValue() { return wbValue; }\r
+  inline int getWBDuration() { return wbDuration; }\r
+\r
+  // setters\r
+  void setValue(const QString& _value);\r
+  inline void resetToDefaultValue() { userValue = defaultValue; }\r
+  inline void setWBAccess(int _wbAccess) { wbAccess = _wbAccess; }\r
+  inline void setWBValue(QString _wbValue) { wbValue = _wbValue; }\r
+  inline void setWBDuration(int _wbDuration) { wbDuration = _wbDuration; }\r
+\r
+  // testers\r
+  bool isValueSet();\r
+  bool isDefaultValue();\r
+  bool isWishboneParameter();\r
+\r
+  // others\r
+  BlockParameter* clone();\r
+  QString toVHDL(int context, int flags);\r
+\r
+private:\r
+\r
+  QString width;\r
+  QVariant userValue;\r
+  int wbAccess;\r
+  QString wbValue;\r
+  int wbDuration;\r
+\r
+\r
+};\r
+\r
+#endif // __BLOCKPARAMETERWISHBONE_H__\r
+\r
diff --git a/BlockWidget.cpp b/BlockWidget.cpp
new file mode 100644 (file)
index 0000000..3b8a658
--- /dev/null
@@ -0,0 +1,300 @@
+#include "BlockWidget.h"\r
+\r
+using namespace std;\r
+using namespace Qt;\r
+\r
+BlockWidget::BlockWidget(QWidget *parent) : QWidget(parent)\r
+{\r
+\r
+    rxComment = new QRegExp("(.*)--.*");\r
+    rxComma = new QRegExp("(.*)[;]");\r
+    rxPort = new QRegExp("[\\s\\t]*(.*)[\\s\\t]*:[\\s\\t]*(in|out|inout)[\\s\\t]*(.*)",CaseInsensitive,QRegExp::RegExp);\r
+    rxEnt = new QRegExp("[\\s\\t]*entity[\\s\\t]*(.*)[\\s\\t]*is",CaseInsensitive,QRegExp::RegExp);\r
+    rxArch = new QRegExp("[\\s\\t]*architecture[\\s\\t]*(.*)[\\s\\t]*of (.*)[\\s\\t]*is",CaseInsensitive,QRegExp::RegExp);\r
+    rxComp = new QRegExp("[\\s\\t]*component[\\s\\t]*(.*)[\\s\\t]*",CaseInsensitive,QRegExp::RegExp);\r
+    rxEnd = new QRegExp("[\\s\\t]*end(.*)",CaseInsensitive,QRegExp::RegExp);\r
+    rxComp = new QRegExp("[\\s\\t]*end component;",CaseInsensitive,QRegExp::RegExp);\r
+    rxGeneric = new QRegExp("[\\s\\t]*generic[\\s\\t]*[(][\\s\\t]*",CaseInsensitive,QRegExp::RegExp);\r
+    rxEndGen = new QRegExp("[\\s\\t]*[)]",CaseInsensitive,QRegExp::RegExp);\r
+    rxGen = new QRegExp("[\\s\\t]*(.*)[\\s\\t]*:[\\s\\t]*(.*)[\\s\\t]*:=[\\s\\t]*(.*)",CaseInsensitive,QRegExp::RegExp);\r
+    rxConst = new QRegExp("[\\s\\t]*constant[\\s\\t]*(.*)[\\s\\t]*:[\\s\\t]*(.)*[\\s\\t]*:=[\\s\\t]*(.*)",CaseInsensitive,QRegExp::RegExp);\r
+    rxWidth = new QRegExp(".*[(](.*)(downto|to)(.*)[)]",CaseInsensitive,QRegExp::RegExp);\r
+\r
+    loadBt = new QPushButton("load VHDL");\r
+    genBt = new QPushButton("generate XML");\r
+    QHBoxLayout *widgetLayout = new QHBoxLayout;\r
+    QVBoxLayout *left = new QVBoxLayout;\r
+    QVBoxLayout *right = new QVBoxLayout;\r
+\r
+    scrollPort = new QScrollArea;\r
+    scrollPort->setWidgetResizable(true);\r
+    twPort = new QTableWidget(this);\r
+    scrollPort->setWidget(twPort);\r
+    scrollGen = new QScrollArea;\r
+    scrollGen->setWidgetResizable(true);\r
+    twGen = new QTableWidget(this);\r
+    scrollGen->setWidget(twGen);\r
+    teName = new QTextEdit;\r
+    teBrief = new QTextEdit;\r
+    teDesc = new QTextEdit;\r
+    lblName = new QLabel("Block name :");\r
+    lblBrief = new QLabel("Enter a brief description : ");\r
+    lblDesc = new QLabel("Enter a detailled description : ");\r
+    lblPort = new QLabel("Ports :");\r
+    lblGen = new QLabel("Generics :");\r
+\r
+    connect(loadBt, SIGNAL(clicked()),this, SLOT(loadCode()));\r
+    connect(genBt, SIGNAL(clicked()), this, SLOT(generateXml()));\r
+\r
+    left->addWidget(loadBt);\r
+    left->addWidget(lblPort);\r
+    left->addWidget(scrollPort);\r
+    left->addWidget(lblGen);\r
+    left->addWidget(scrollGen);\r
+\r
+    right->addWidget(lblName);\r
+    right->addWidget(teName);\r
+    right->addWidget(lblBrief);\r
+    right->addWidget(teBrief);\r
+    right->addWidget(lblDesc);\r
+    right->addWidget(teDesc);\r
+    right->addWidget(genBt);\r
+\r
+    widgetLayout->addLayout(left);\r
+    widgetLayout->addLayout(right);\r
+    setLayout(widgetLayout);\r
+    show();\r
+}\r
+\r
+BlockWidget::~BlockWidget()\r
+{\r
+\r
+}\r
+\r
+// This function opens a VHDL file and get the informations about the entity :\r
+// First the generics, then the signals.\r
+// You can edit the descriptions in the right, one for the brief description, the other for the detailled.\r
+void BlockWidget::loadCode() {\r
+\r
+    QString line, portName, portType, portId, genName, genType, genValue;\r
+    QStringList *portNameList, *portTypeList, *portIdList, *genNameList, *genTypeList, *genValueList;\r
+    cpt = 0;\r
+    twPort->setColumnCount(3);\r
+    twPort->setRowCount(cpt);\r
+    twGen->setColumnCount(3);\r
+    twGen->setRowCount(cpt);\r
+    portNameList = new QStringList;\r
+    portTypeList = new QStringList;\r
+    portIdList = new QStringList;\r
+    genNameList = new QStringList;\r
+    genTypeList = new QStringList;\r
+    genValueList = new QStringList;\r
+\r
+    fileName = QFileDialog::getOpenFileName(this,\r
+                                            tr("Open File"), "C:", tr("Files (*.txt *.vhd)"));\r
+    QFile file(fileName);\r
+\r
+    if(!file.open(QIODevice::ReadOnly | QIODevice::Text))\r
+        return;\r
+    QTextStream ts(&file);\r
+    while (!ts.atEnd())\r
+    {\r
+        line = ts.readLine();\r
+        if(rxComment->indexIn(line) != -1) {\r
+            line = rxComment->cap(1);\r
+        }\r
+\r
+        if(rxEnt->indexIn(line)!= -1) {\r
+\r
+            entName = rxEnt->cap(1);\r
+            teName->setText(entName);\r
+            QSize size = teName->document()->size().toSize();\r
+            teName->setMaximumSize(size);\r
+\r
+            while(rxEnd->indexIn(line) == -1) {\r
+                line = ts.readLine();\r
+                if(rxComment->indexIn(line) != -1) {\r
+                    line = rxComment->cap(1);\r
+                }\r
+                if(rxComma->indexIn(line) != -1) {\r
+                    line = rxComma->cap(1);\r
+                }\r
+                if(rxGeneric->indexIn(line) != -1) {\r
+                    while(rxEndGen->indexIn(line) == -1) {\r
+                        line = ts.readLine();\r
+                        if(rxComment->indexIn(line) != -1) {\r
+                            line = rxComment->cap(1);\r
+                        }\r
+                        if(rxComma->indexIn(line) != -1) {\r
+                            line = rxComma->cap(1);\r
+                        }\r
+                        if(rxGen->indexIn(line) != -1) {\r
+                            genName = rxGen->cap(1).simplified();\r
+                            genType = rxGen->cap(2).simplified();\r
+                            genValue = rxGen->cap(3).simplified();\r
+\r
+                            genNameList->append(genName);\r
+                            genTypeList->append(genType);\r
+                            genValueList->append(genValue);\r
+                        }\r
+                    }\r
+                }\r
+                if(rxPort->indexIn(line) != -1) {\r
+                    if(rxComment->indexIn(line) != -1) {\r
+                        line = rxComment->cap(1);\r
+                    }\r
+                    if(rxComma->indexIn(line) != -1) {\r
+                        line = rxComma->cap(1);\r
+                    }\r
+                    portName = rxPort->cap(1).simplified();\r
+                    portId = rxPort->cap(2).simplified();\r
+                    portType = rxPort->cap(3).simplified();\r
+                    portNameList->append(portName);\r
+                    portIdList->append(portId);\r
+                    portTypeList->append(portType);\r
+                }\r
+            }\r
+        }\r
+    }\r
+\r
+    twGen->setRowCount(genNameList->size());\r
+    for(int i = 0; i < genNameList->size(); i++) {\r
+        twGen->setItem(i, 0, new QTableWidgetItem(genNameList->at(i)));\r
+        twGen->setItem(i, 1, new QTableWidgetItem(genTypeList->at(i)));\r
+        twGen->setItem(i, 2, new QTableWidgetItem(genValueList->at(i)));\r
+    }\r
+    twPort->setRowCount(portNameList->size());\r
+    for(int i = 0; i < portNameList->size(); i++) {\r
+        twPort->setItem(i, 0, new QTableWidgetItem(portIdList->at(i)));\r
+        twPort->setItem(i, 1, new QTableWidgetItem(portNameList->at(i)));\r
+        twPort->setItem(i, 2, new QTableWidgetItem(portTypeList->at(i)));\r
+    }\r
+\r
+    file.close();\r
+    scrollPort->setWidget(twPort);\r
+    return;\r
+}\r
+\r
+// This function gets the informations in the table and the descriptions, and creates a XML file with this content\r
+void BlockWidget::generateXml() {\r
+\r
+    QString portName, portType, portId, genName, genType, genValue;\r
+    QStringList *portNameList, *portTypeList, *portIdList, *genNameList, *genTypeList, *genValueList;\r
+    int x, y, width;\r
+    brief = teBrief->toPlainText();\r
+    desc = teDesc->toPlainText();\r
+    entName = teName->toPlainText();\r
+\r
+    portNameList = new QStringList;\r
+    portTypeList = new QStringList;\r
+    portIdList = new QStringList;\r
+    genNameList = new QStringList;\r
+    genTypeList = new QStringList;\r
+    genValueList = new QStringList;\r
+    for(int i = 0; i < twGen->rowCount(); i++) {\r
+        genNameList->append(twGen->item(i,0)->text());\r
+        genTypeList->append(twGen->item(i,1)->text());\r
+        genValueList->append(twGen->item(i,2)->text());\r
+    }\r
+\r
+    for(int i = 0; i < twPort->rowCount(); i++) {\r
+        portIdList->append(twPort->item(i,0)->text());\r
+        portNameList->append(twPort->item(i,1)->text());\r
+        portTypeList->append(twPort->item(i,2)->text());\r
+    }\r
+\r
+    QDomDocument doc (entName);\r
+    QDomElement block = doc.createElement("block");\r
+    block.setAttribute("name",entName);\r
+    block.setAttribute("version", "0.1");\r
+    doc.appendChild(block);\r
+\r
+    QDomElement comments = doc.createElement("comments");\r
+    QDomElement category = doc.createElement("caterory");\r
+    category.setAttribute("ids","");\r
+    comments.appendChild(category);\r
+\r
+    QDomElement eBrief = doc.createElement("brief");\r
+    if(!brief.isEmpty()) {\r
+        QDomText txtBrief = doc.createTextNode(brief);\r
+        eBrief.appendChild(txtBrief);\r
+        comments.appendChild(eBrief);\r
+    }\r
+    QDomElement eDesc = doc.createElement("description");\r
+    if(!desc.isEmpty()) {\r
+        QDomText txtDesc = doc.createTextNode(desc);\r
+        eDesc.appendChild(txtDesc);\r
+        comments.appendChild(eDesc);\r
+    }\r
+    block.appendChild(comments);\r
+\r
+    QDomElement parameters = doc.createElement("parameters");\r
+    QDomElement interfaces = doc.createElement("interfaces");\r
+    QDomElement inputs = doc.createElement("inputs");\r
+    QDomElement outputs = doc.createElement("outputs");\r
+    QDomElement bidirs = doc.createElement("bidirs");\r
+    block.appendChild(parameters);\r
+    block.appendChild(interfaces);\r
+    interfaces.appendChild(inputs);\r
+    interfaces.appendChild(outputs);\r
+    interfaces.appendChild(bidirs);\r
+\r
+    for(int i = 0; i < twGen->rowCount(); i++) {\r
+        genName = genNameList->at(i);\r
+        genType = genTypeList->at(i);\r
+        genValue = genValueList->at(i);\r
+        QDomElement parameter = doc.createElement("parameter");\r
+        parameter.setAttribute("name",genName);\r
+        parameter.setAttribute("type",genType);\r
+        parameter.setAttribute("value",genValue);\r
+        parameter.setAttribute("context","generic");\r
+        parameters.appendChild(parameter);\r
+    }\r
+\r
+    for(int i = 0; i < portIdList->size(); i++) {\r
+        portId = portIdList->at(i);\r
+        portName = portNameList->at(i);\r
+        portType = portTypeList->at(i);\r
+        if(rxWidth->indexIn(portType) != -1) {\r
+            x = rxWidth->cap(1).toInt();\r
+            y = rxWidth->cap(3).toInt();\r
+            if(x < y)\r
+                width = y - x + 1;\r
+            else if(x > y)\r
+                width = x - y + 1;\r
+            else\r
+                width = 1;\r
+        }\r
+\r
+        if(portId.compare("in", CaseInsensitive) == 0) {\r
+            QDomElement input = doc.createElement("input");\r
+            input.setAttribute("name",portName);\r
+            input.setAttribute("width", width);\r
+            inputs.appendChild(input);\r
+        }\r
+        else if(portId.compare("out", CaseInsensitive) == 0) {\r
+            QDomElement output = doc.createElement("output");\r
+            output.setAttribute("name",portName);\r
+            output.setAttribute("width", width);\r
+            outputs.appendChild(output);\r
+        }\r
+        else if(portId.compare("inout", CaseInsensitive) == 0) {\r
+            QDomElement bidir = doc.createElement("bidir");\r
+            bidir.setAttribute("name",portName);\r
+            bidir.setAttribute("width", width);\r
+            bidirs.appendChild(bidir);\r
+        }\r
+    }\r
+\r
+    fileName = QFileDialog::getOpenFileName(this, tr("Open File"),\r
+                                            "C:", tr("Files (*.xml)"));\r
+    QFile file(fileName);\r
+    if(!file.open(QIODevice::WriteOnly | QIODevice::Text))\r
+        return;\r
+    QTextStream ts(&file);\r
+    doc.save(ts,QDomNode::EncodingFromTextStream);\r
+    file.close();\r
+\r
+    QLabel *popup = new QLabel("Votre fichier XML est rempli");\r
+    popup->show();\r
+}\r
diff --git a/BlockWidget.h b/BlockWidget.h
new file mode 100644 (file)
index 0000000..9150928
--- /dev/null
@@ -0,0 +1,42 @@
+#ifndef ENTITYWIDGET_H\r
+#define ENTITYWIDGET_H\r
+\r
+#include <QtGui>\r
+#include <QtWidgets>\r
+#include <QtCore>\r
+#include <QtXml>\r
+#include <iostream>\r
+#include <fstream>\r
+#include <QTextStream>\r
+\r
+#include "Parameters.h"\r
+#include "BlockParameter.h"\r
+#include "Graph.h"\r
+\r
+class BlockWidget : public QWidget\r
+{\r
+    Q_OBJECT\r
+public:\r
+    explicit BlockWidget(QWidget *parent = 0);\r
+    ~BlockWidget();\r
+\r
+private:\r
+    QPushButton *loadBt, *genBt;\r
+    int cptIn, cptOut, cptInout, cpt;\r
+    QRegExp *rxPort, *rxEnt, *rxArch, *rxComp, *rxComment, *rxComma,\r
+    *rxEndComp, *rxEnd, *rxGeneric, *rxEndGen, *rxGen, *rxConst, *rxWidth;\r
+    QString fileName, txt, s, entName, brief, desc;\r
+    QScrollArea *scrollPort, *scrollGen;\r
+    QWidget *wid;\r
+    QLabel *labelAppli, *lblBrief, *lblDesc, *lblName, *lblPort, *lblGen;\r
+    QTableWidget *twPort, *twGen;\r
+    QTextEdit *teBrief, *teDesc, *teName;\r
+\r
+signals:\r
+\r
+public slots:\r
+    void loadCode();\r
+    void generateXml();\r
+};\r
+\r
+#endif // ENTITYWIDGET_H\r
diff --git a/BlocksToConfigureWidget.cpp b/BlocksToConfigureWidget.cpp
new file mode 100644 (file)
index 0000000..f860e52
--- /dev/null
@@ -0,0 +1,77 @@
+#include "BlocksToConfigureWidget.h"
+#include <QTreeWidgetItem>
+#include "ParametersWindow.h"
+
+
+BlocksToConfigureWidget::BlocksToConfigureWidget(QList<AbstractBlock *> blocksList, Parameters *_params, QWidget *parent) :
+    QWidget(parent)
+{
+  blocks = blocksList;
+  params = _params;
+  layout = new QGridLayout;
+  tree = new QTreeWidget(this);
+  configureButton = new QPushButton("configure", this);
+  configureButton->setEnabled(false);
+
+  connect(tree, SIGNAL(itemClicked(QTreeWidgetItem*,int)), this, SLOT(clicked()));
+  connect(tree, SIGNAL(itemDoubleClicked(QTreeWidgetItem*,int)), this, SLOT(doubleClicked()));
+  connect(configureButton, SIGNAL(clicked()), this, SLOT(configure()));
+
+  updateNamesList();
+  tree->setHeaderLabel("blocks to configure");
+  layout->addWidget(tree);
+  layout->addWidget(configureButton);
+
+  this->setLayout(layout);
+  this->setFixedSize(300,230);
+}
+
+void BlocksToConfigureWidget::updateNamesList()
+{
+  tree->clear();
+  QTreeWidgetItem *item = NULL;
+  foreach(AbstractBlock *block, blocks){
+    item = new QTreeWidgetItem(tree->invisibleRootItem());
+    item->setData(0, Qt::DisplayRole, block->getName());
+  }
+
+}
+
+void BlocksToConfigureWidget::updateBlocksList()
+{
+  blocks = params->getBlocksToConfigure();
+  updateNamesList();
+}
+
+void BlocksToConfigureWidget::closeEvent(QCloseEvent *event)
+{
+  //when parameters validation is over,
+  //we start connections validation.
+  params->connectionsValidation();
+}
+
+void BlocksToConfigureWidget::clicked()
+{
+  if(tree->selectedItems().length() > 0)
+    configureButton->setEnabled(true);
+  else
+    configureButton->setEnabled(false);
+}
+
+void BlocksToConfigureWidget::doubleClicked()
+{
+  configure();
+}
+
+void BlocksToConfigureWidget::configure()
+{
+  if(tree->selectedItems().length() > 0){
+    bool firstItem = true;  //    We take only the first selected item
+    for (int i=0; i<tree->topLevelItemCount(); i++){
+      if(firstItem && tree->topLevelItem(i)->isSelected()){
+        firstItem = false;
+        new ParametersWindow(blocks.at(i), params, this);
+      }
+    }
+  }
+}
diff --git a/BlocksToConfigureWidget.h b/BlocksToConfigureWidget.h
new file mode 100644 (file)
index 0000000..52b31fc
--- /dev/null
@@ -0,0 +1,39 @@
+#ifndef __BLOCKSTOCONFIGUREWIDGET_H__
+#define __BLOCKSTOCONFIGUREWIDGET_H__
+
+#include <QWidget>
+
+#include <QTreeWidget>
+#include <QGridLayout>
+#include "Parameters.h"
+#include "AbstractBlock.h"
+#include <QPushButton>
+
+class BlocksToConfigureWidget : public QWidget
+{
+    Q_OBJECT
+public:
+    BlocksToConfigureWidget(QList<AbstractBlock *> blocksList, Parameters *_params, QWidget *parent=0);
+
+    void updateNamesList();
+    void updateBlocksList();
+
+    inline QTreeWidget *getTree() { return tree; }
+    inline QList<AbstractBlock*> getBlocks() { return blocks; }
+
+private:
+    void closeEvent(QCloseEvent * event);
+
+    QList<AbstractBlock*> blocks;
+    QTreeWidget *tree;
+    QGridLayout *layout;
+    QPushButton *configureButton;
+    Parameters *params;
+
+private slots:
+    void clicked();
+    void doubleClicked();
+    void configure();
+};
+
+#endif // BLOCKSTOCONFIGUREWIDGET_H
diff --git a/BoxItem.cpp b/BoxItem.cpp
new file mode 100644 (file)
index 0000000..77e9533
--- /dev/null
@@ -0,0 +1,681 @@
+#include "BoxItem.h"
+#include "GroupScene.h"
+#include "ConnectionItem.h"
+#include "InterfaceItem.h"
+#include "GroupItem.h"
+#include "Parameters.h"
+#include "Exception.h"
+#include "Dispatcher.h"
+#include "FunctionalBlock.h"
+#include "FunctionalInterface.h"
+#include "ReferenceInterface.h"
+#include "ReferenceBlock.h"
+#include "ParametersWindow.h"
+#include "BlockParameter.h"
+
+
+BoxItem::BoxItem(AbstractBlock *_refBlock,
+                     Dispatcher *_dispatcher,
+                     Parameters *_params, GroupItem *parent) throw(Exception) : AbstractBoxItem( _refBlock, _dispatcher, _params, parent) {
+
+  /*  NOTE :
+     _refBlock : mandatory a FunctionalBlock or a GroupBlock
+  */
+  if (_refBlock->isReferenceBlock()) throw(Exception(BLOCK_INVALID_TYPE));
+
+  childGroupItem = NULL;
+  //boxWidth = params->defaultBlockWidth;
+  //boxHeight = params->defaultBlockHeight;
+  currentBorder = NoBorder;
+  selected = false;
+
+  setZValue(100);
+  setFlags(QGraphicsItem::ItemIsMovable | QGraphicsItem::ItemIsSelectable | QGraphicsItem::ItemSendsGeometryChanges);
+
+  initInterfaces();
+  updateGeometry();
+  resetInterfacesPosition();
+  QPointF initPos = QPointF(0.0,0.0) - originPoint;
+  setPos(initPos);
+  //cout << "total size of block: " << totalWidth << "," << totalHeight << endl;
+  //cout << "pos in group: " << x() << "," << y() << endl;
+}
+
+
+BoxItem::~BoxItem() {
+}
+
+void BoxItem::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget) {
+  QPen pen(Qt::black, 3);
+  if(selected)
+    pen.setColor(Qt::red);
+
+  painter->setPen(pen);
+  painter->setBrush(Qt::yellow);
+
+  painter->drawRect(0,0,boxWidth, boxHeight);
+  painter->drawText(0,0,boxWidth, boxHeight,Qt::AlignCenter | Qt::TextWordWrap,QString(refBlock->getName()));
+  foreach(InterfaceItem *inter, interfaces) {
+    inter->paint(painter);
+  }
+}
+
+void BoxItem::moveTo(QPointF dest) {
+  setPos(dest);
+  currentPosition = dest;
+}
+
+bool BoxItem::isBoxItem() {
+  return true;
+}
+
+void BoxItem::updateMinimumSize() {
+
+  int maxSouth = 0;
+  int maxNorth = 0;
+  int maxEast = 0;
+  int maxWest = 0;
+  int nbSouth = nbInterfacesByOrientation(Parameters::South);
+  int nbNorth = nbInterfacesByOrientation(Parameters::North);
+  int nbMaxSN = nbNorth;
+  if (nbSouth > nbNorth) nbMaxSN = nbSouth;
+  int nbEast = nbInterfacesByOrientation(Parameters::East);
+  int nbWest = nbInterfacesByOrientation(Parameters::West);
+  int nbMaxEW = nbEast;
+  if (nbWest > nbEast) {
+    nbMaxEW = nbWest;
+  }
+
+  int ifaceWidth = 0;
+  int ifaceHeight = 0;
+
+  foreach(InterfaceItem* iface, interfaces) {
+    ifaceWidth = iface->getNameWidth();
+    ifaceHeight = iface->getNameHeight();
+    if (iface->getOrientation() == Parameters::South) {
+      if (ifaceWidth > maxSouth) maxSouth = ifaceWidth;
+    }
+    else if (iface->getOrientation() == Parameters::North) {
+      if (ifaceWidth > maxNorth) maxNorth = ifaceWidth;
+    }
+    else if (iface->getOrientation() == Parameters::East) {
+      if (ifaceWidth > maxEast) maxEast = ifaceWidth;
+    }
+    else if (iface->getOrientation() == Parameters::West) {
+      if (ifaceWidth > maxWest) maxWest = ifaceWidth;
+    }
+  }
+
+  /* NB: the width layout is the following
+     ifaceMargin | maxWest | nameMargin | name | nameMargin | maxEast | ifaceMargin
+   */
+  minimumBoxWidth = maxWest+maxEast+nameWidth+2*(ifaceMargin+nameMargin);
+  // if the minimum is not sufficent taking into account N/S interfaces
+  if (minimumBoxWidth < (nbMaxSN*ifaceHeight+ifaceMargin*(nbMaxSN+1))) {
+    minimumBoxWidth = (nbMaxSN*ifaceHeight+ifaceMargin*(nbMaxSN+1));
+  }
+  minimumBoxHeight = maxNorth+maxSouth+3*ifaceMargin;
+  if (minimumBoxHeight < (nbMaxEW*ifaceHeight+ifaceMargin*(nbMaxEW+1))) {
+    minimumBoxHeight = (nbMaxEW*ifaceHeight+ifaceMargin*(nbMaxEW+1));
+  }
+}
+
+
+/* updateGeometry() :
+
+ */
+bool BoxItem::updateGeometry(ChangeType type) {
+
+  currentPosition = pos();
+  //cout << "current pos of block: " << currentPosition.x() << "," << currentPosition.y() << endl;
+  QPointF oldOrigin = originPoint;
+  QSize oldSize(totalWidth,totalHeight);
+
+  bool boxSizeChanged = false;
+
+  if ((type == Resize) || (type == InterfaceMove)) {
+    updateMinimumSize();
+  }
+
+  if (type == Resize) {
+    prepareGeometryChange();
+    updateInterfacesAndConnections();
+    boxSizeChanged = true;
+  }
+  if (boxWidth < minimumBoxWidth) {
+    boxWidth = minimumBoxWidth;
+    boxSizeChanged = true;
+  }
+  if (boxHeight < minimumBoxHeight) {
+    boxHeight = minimumBoxHeight;
+     boxSizeChanged = true;
+  }
+  if (boxSizeChanged) {
+    updateInterfacesAndConnections();
+  }
+
+  double x = 0.0;
+  double y = 0.0;
+  totalWidth = boxWidth;
+  totalHeight = boxHeight;
+
+  if(isInterfaces(Parameters::East)){
+    totalWidth += params->arrowWidth+params->arrowLineLength;
+  }
+  if(isInterfaces(Parameters::West)){
+    totalWidth += params->arrowWidth+params->arrowLineLength;
+    x -= params->arrowWidth+params->arrowLineLength;
+  }
+  if(isInterfaces(Parameters::South)){
+    totalHeight += params->arrowWidth+params->arrowLineLength;
+  }
+  if(isInterfaces(Parameters::North)){
+    totalHeight += params->arrowWidth+params->arrowLineLength;
+    y -= params->arrowWidth+params->arrowLineLength;
+  }
+  QSizeF newSize(totalWidth,totalHeight);
+  originPoint.setX(x);
+  originPoint.setY(y);
+
+  if ((boxSizeChanged) || (newSize != oldSize) || (originPoint != oldOrigin)) {
+    prepareGeometryChange();
+    return true;
+  }
+  return false;
+}
+
+void BoxItem::mouseMoveEvent(QGraphicsSceneMouseEvent *event) {
+
+  if(params->editState == Parameters::EditBlockMove) {
+    QPointF absPos = currentPosition + originPoint;
+    int marginConn = 2*(params->arrowWidth+params->arrowLineLength);
+    int gapX = event->scenePos().x() - cursorPosition.x();
+    int gapY = event->scenePos().y() - cursorPosition.y();
+
+    //cout << "block abs. pos: " << absPos.x() << "," << absPos.y() << " | ";
+    //cout << "block current. pos: " << currentPosition.x() << "," << currentPosition.y() << " | ";
+
+    if (absPos.x()+gapX < marginConn) {
+      gapX = marginConn-absPos.x();
+    }
+    if (absPos.y()+gapY < marginConn) {
+      gapY = marginConn-absPos.y();
+    }
+    //cout << "gap: " << gapX << "," << gapY << endl;
+    QPointF gap(gapX,gapY);
+    currentPosition = currentPosition+gap;
+    setPos(currentPosition);
+    // update all connections from/to this block
+    foreach(ConnectionItem *item, getScene()->getConnectionItems()){
+      if ((item->getFromInterfaceItem()->getOwner() == this) || (item->getToInterfaceItem()->getOwner() == this)) {
+        item->setPathes();
+      }
+    }
+    cursorPosition = event->scenePos();
+
+    // udpate the groupitem
+    (getScene()->getGroupItem())->updateShape();
+  }
+  else if(params->editState == Parameters::EditBlockResize) {
+
+    int gapX = event->scenePos().x() - cursorPosition.x();
+    int gapY = event->scenePos().y() - cursorPosition.y();
+    //cout << "gap: " << gapX << "," << gapY << endl;
+    switch(currentBorder){
+    case BorderEast: {    
+      if(boxWidth+gapX > minimumBoxWidth){
+        boxWidth += gapX;
+      }
+      break;
+    }
+    case BorderSouth: {      
+      if(boxHeight+gapY > minimumBoxHeight){
+        boxHeight += gapY;
+      }
+      break;
+    }
+    case CornerSouthEast: {
+      if(boxWidth+gapX > minimumBoxWidth){
+        boxWidth += gapX;
+      }
+      if(boxHeight+gapY > minimumBoxHeight){
+        boxHeight += gapY;
+      }
+      break;
+    }
+    case NoBorder:
+      cout << "abnormal case while resizing block" << endl;
+      break;
+    }
+    // recompute the geometry of the block and possibly the group item
+    if (updateGeometry()) {
+      (getScene()->getGroupItem())->updateShape();
+    }
+
+    cursorPosition = event->scenePos();   
+  }
+  else if(params->editState == Parameters::EditInterfaceMove) {
+    prepareGeometryChange();
+    deplaceInterface(event->pos());
+    // recompute the geometry of the block
+    if (updateGeometry()) {
+      cout << "must recompute group item geometry" << endl;
+      (getScene()->getGroupItem())->updateShape();
+    }
+    // update connection from/to the selected interface
+    foreach(ConnectionItem *item, getScene()->getConnectionItems()){
+      if ((item->getFromInterfaceItem() == currentInterface) || (item->getToInterfaceItem() == currentInterface)) {
+        item->setPathes();
+      }
+    }    
+  }
+}
+
+void BoxItem::mousePressEvent(QGraphicsSceneMouseEvent *event) {
+
+  QPointF pos = event->pos();
+  qreal x = pos.x();
+  qreal y = pos.y();
+
+  //QGraphicsItem::mousePressEvent(event);
+
+  if(event->button() == Qt::RightButton) return;
+
+  int mode = getScene()->getEditionMode();
+
+  dispatcher->setCurrentGroupWidget(getScene()->getGroupWindow());
+
+  if ((mode == GroupScene::AddConnection) && (params->cursorState == Parameters::CursorOnInterface)) {
+    InterfaceItem *inter = getInterfaceFromCursor(x,y);
+    if (inter != NULL) {
+
+      if (params->editState == Parameters::EditNoOperation) {
+        getScene()->setSelectedInterface(1,inter);
+        params->setEditState(Parameters::EditStartConnection);
+      }
+      else if (params->editState == Parameters::EditStartConnection) {
+        if (inter == getScene()->getSelectedInterface(1)) {
+          params->setEditState(Parameters::EditAbortConnection);
+        }
+        else {
+          getScene()->setSelectedInterface(2,inter);
+          params->setEditState(Parameters::EditCloseConnection);
+        }
+      }
+    }
+  }
+  else if (mode == GroupScene::ItemEdition) {
+    setZValue(zValue()+100);
+    if (params->cursorState == Parameters::CursorOnInterface) {
+      InterfaceItem *inter = getInterfaceFromCursor(x,y);
+      if (inter != NULL) {
+        if (inter == currentInterface) {
+           params->setEditState(Parameters::EditInterfaceDeselect);
+        }
+        else {
+          setFlag(ItemIsMovable, false);
+          currentInterface = inter;
+          params->setEditState(Parameters::EditInterfaceMove);
+        }
+      }
+    }
+    else if (params->cursorState == Parameters::CursorInBlock) {
+      selected = !selected;
+      params->setEditState(Parameters::EditBlockMove);
+      cursorPosition = event->scenePos();
+      //cout << "cursor current pos. in scene " << cursorPosition.x() << "," << cursorPosition.y() << endl;
+      update();
+    }
+    else if (params->cursorState == Parameters::CursorOnBorder) {
+      setFlag(ItemIsMovable, false);
+      cursorPosition = event->scenePos();
+      params->setEditState(Parameters::EditBlockResize);
+    }
+  }
+}
+
+void BoxItem::mouseReleaseEvent(QGraphicsSceneMouseEvent  *event) {
+
+  setZValue(zValue()-100);
+
+  int mode = getScene()->getEditionMode();
+
+  if (mode == GroupScene::AddConnection) {
+
+    if (params->editState == Parameters::EditStartConnection) {
+      InterfaceItem* iface = getScene()->getSelectedInterface(1);
+      iface->selected = true;
+      update(iface->boundingRect());
+    }
+    else if (params->editState == Parameters::EditAbortConnection) {
+      InterfaceItem* iface = getScene()->getSelectedInterface(1);
+      iface->selected = false;
+      update(iface->boundingRect());
+      getScene()->setSelectedInterface(1,NULL);
+      params->setEditState(Parameters::EditNoOperation);
+    }
+    else if (params->editState == Parameters::EditCloseConnection) {
+      InterfaceItem* iface1 = getScene()->getSelectedInterface(1);
+      InterfaceItem* iface2 = getScene()->getSelectedInterface(2);
+      bool ok = dispatcher->connect(iface1,iface2);
+      if (ok) {
+        iface1->selected = false;
+        // no update needed since the whole scene will be repainted
+        getScene()->setSelectedInterface(1,NULL);
+        getScene()->setSelectedInterface(2,NULL);
+        params->setEditState(Parameters::EditNoOperation);
+      }
+      else {
+        getScene()->setSelectedInterface(2,NULL);
+        params->setEditState(Parameters::EditStartConnection);
+      }
+    }
+  }
+  else if (mode == GroupScene::ItemEdition) {
+    currentInterface = NULL;
+    params->editState = Parameters::EditNoOperation;
+    setFlag(ItemIsMovable);
+  }
+
+  QGraphicsItem::mouseReleaseEvent(event);
+}
+
+void BoxItem::hoverMoveEvent(QGraphicsSceneHoverEvent * event) {
+
+  QPointF pos = event->pos();
+  qreal x = pos.x();
+  qreal y = pos.y();
+  currentBorder = NoBorder;
+  int mode = getScene()->getEditionMode();
+
+  if (mode == GroupScene::AddConnection) {
+    InterfaceItem* iface = getInterfaceFromCursor(x,y);
+    if (iface != NULL) {
+      params->cursorState = Parameters::CursorOnInterface;
+      setCursor(Qt::PointingHandCursor);
+    }
+    else {
+      params->cursorState = Parameters::CursorNowhere;
+      setCursor(Qt::ArrowCursor);
+    }
+  }
+  else if (mode == GroupScene::ItemEdition) {
+    int marginE = 5;
+    int marginS = 5;
+
+    InterfaceItem* iface = getInterfaceFromCursor(x,y);
+    if (iface != NULL) {
+      params->cursorState = Parameters::CursorOnInterface;
+      setCursor(Qt::PointingHandCursor);
+    }
+    else if ((x>boxWidth-marginE)&&(x<boxWidth)) {
+
+      params->cursorState = Parameters::CursorOnBorder;
+
+      if ((y>boxHeight-2*marginS)&&(y<boxHeight)) {
+        currentBorder = CornerSouthEast;
+        setCursor(Qt::SizeFDiagCursor);
+      }
+      else {
+        currentBorder = BorderEast;
+        setCursor(Qt::SizeHorCursor);
+      }
+    }
+    else if ((y>boxHeight-marginS)&&(y<boxHeight)) {
+
+      params->cursorState = Parameters::CursorOnBorder;
+
+      if ((x>boxWidth-2*marginE)&&(x<boxWidth)) {
+        currentBorder = CornerSouthEast;
+        setCursor(Qt::SizeFDiagCursor);
+      }
+      else {
+        currentBorder = BorderSouth;
+        setCursor(Qt::SizeVerCursor);
+      }
+    }
+    else {
+      if ((x>0) && (x<boxWidth-marginE) && (y>0) && (y<boxHeight-marginS)) {
+        params->cursorState = Parameters::CursorInBlock;
+        setCursor(Qt::OpenHandCursor);
+      }
+      else {
+        params->cursorState = Parameters::CursorNowhere;
+        setCursor(Qt::ArrowCursor);
+      }
+    }
+  }
+  QGraphicsItem::hoverMoveEvent(event);
+}
+
+
+void BoxItem::contextMenuEvent(QGraphicsSceneContextMenuEvent * event) {
+
+  QMenu menu;
+  QAction* removeAction = menu.addAction("Remove");
+  QAction* duplicateAction = menu.addAction("Duplicate");
+  QAction* renameAction = menu.addAction("Rename");
+  QAction* connectToGroup = NULL;
+  QAction* disconnectFromGroup = NULL;
+  QAction* showProperties = NULL;
+  QAction* cloneInterface = NULL;
+  QAction* openWindow = NULL;
+  QAction* showRstClkInter = NULL;
+  QAction* showParameters = NULL;
+
+  InterfaceItem* ifaceItem = getInterfaceFromCursor(event->pos().x(), event->pos().y());
+  if( ifaceItem != NULL){
+    showProperties = menu.addAction("Show properties");
+
+    ConnectedInterface* iface = ifaceItem->refInter;
+    if ((iface->getDirection() == AbstractInterface::Input) && (iface->getConnectedFrom() == NULL)) {
+        connectToGroup = menu.addAction("Connect to group input");
+    }
+    else if ((iface->getDirection() == AbstractInterface::Output) && (!iface->isConnectedTo())) {
+      connectToGroup = menu.addAction("Connect to group output");
+    }
+    else if ((iface->getConnectionFromParentGroup() != NULL) || (iface->getConnectionToParentGroup() != NULL)) {
+      disconnectFromGroup = menu.addAction("Disconnect from group");
+    }
+
+    if (iface->isFunctionalInterface()) {
+      FunctionalInterface* fi = AI_TO_FUN(ifaceItem->refInter);
+      ReferenceInterface* ri = (ReferenceInterface*)(fi->getReference());
+      if(ri->getMultiplicity() == -1 || ri->getMultiplicity() > 1){
+        cloneInterface = menu.addAction("Clone interface");
+      }
+    }
+  }
+  if(refBlock->isGroupBlock()){
+    openWindow = menu.addAction("Open/show group window");
+  } else {
+    showRstClkInter = menu.addAction("Show reset/clock interfaces");
+    showRstClkInter->setCheckable(true);
+    showRstClkInter->setChecked(rstClkVisible);
+
+    showParameters = menu.addAction("Show parameters");
+  }
+
+  QAction* selectedAction = NULL;
+  selectedAction = menu.exec(event->screenPos());
+
+  if(selectedAction == NULL) return ;
+
+  if (selectedAction == removeAction) {
+    dispatcher->removeBlock(this);
+  }
+  else if (selectedAction == duplicateAction) {
+    dispatcher->duplicateBlock(this);
+  }
+  else if(selectedAction == renameAction){
+    if(ifaceItem != NULL)
+      dispatcher->rename(ifaceItem);
+    else
+      dispatcher->rename(this);
+  }
+  else if(selectedAction == showProperties){
+    dispatcher->showProperties(ifaceItem);
+  }
+  else if (selectedAction == connectToGroup){
+    dispatcher->connectInterToGroup(ifaceItem);
+  }
+  else if (selectedAction == disconnectFromGroup) {
+    dispatcher->disconnectInterFromGroup(ifaceItem);
+  }
+  else if (selectedAction == cloneInterface){
+    dispatcher->duplicateInterface(ifaceItem);
+  }
+  else if (selectedAction == openWindow){
+    dispatcher->showRaiseWindow(this);
+  }
+  else if(selectedAction == showRstClkInter){
+    dispatcher->showRstClkInter(this);
+  }
+  else if(selectedAction == showParameters){
+    new ParametersWindow(refBlock, params, NULL);
+  }
+}
+
+void BoxItem::save(QXmlStreamWriter &writer) {
+  if (refBlock->isFunctionalBlock()) {
+    writer.writeStartElement("bi_functional");
+
+    writer.writeAttribute("id",QString::number(id));
+    writer.writeAttribute("ref_xml", ((FunctionalBlock*)refBlock)->getReferenceXmlFile());
+    writer.writeAttribute("ref_md5", ((FunctionalBlock*)refBlock)->getReferenceHashMd5());
+    writer.writeAttribute("name",refBlock->getName());
+    QString attrPos = QString::number(pos().x()).append(",").append(QString::number(pos().y()));
+    writer.writeAttribute("position",attrPos);
+    QString attrDim = QString::number(getWidth()).append(",").append(QString::number(getHeight()));
+    writer.writeAttribute("dimension",attrDim);
+
+    writer.writeStartElement("bif_parameters");
+    foreach(BlockParameter *param,refBlock->getParameters()){
+      writer.writeStartElement("bif_parameter");
+
+      writer.writeAttribute("name",param->getName());
+      writer.writeAttribute("value",param->getValue().toString());
+      /*
+      writer.writeAttribute("context",param->getStrContext());
+      writer.writeAttribute("type",param->getTypeString());
+      */
+      writer.writeEndElement();   //</bif_parameter>
+    }
+    writer.writeEndElement();   //</bif_parameters>
+
+    writer.writeStartElement("bif_ifaces");
+    writer.writeAttribute("count",QString::number(interfaces.length()));
+    foreach(InterfaceItem* inter, interfaces){
+      writer.writeStartElement("bif_iface");
+
+      writer.writeAttribute("id",QString::number(inter->getId()));
+      writer.writeAttribute("name",inter->getName());
+      writer.writeAttribute("ref_name",inter->refInter->getName());
+      writer.writeAttribute("orientation",inter->getStrOrientation());
+      writer.writeAttribute("position",QString::number(inter->getPositionRatio()));
+
+      writer.writeEndElement();   //</bif_iface>
+    }
+    writer.writeEndElement();   //</bif_ifaces>
+
+    writer.writeEndElement();   //</bi_functional>
+  }
+  else {
+    writer.writeStartElement("bi_group");
+
+    writer.writeAttribute("id",QString::number(id));
+    writer.writeAttribute("inside_group",QString::number(childGroupItem->getId()));
+    QString attrPos = QString::number(pos().x()).append(",").append(QString::number(pos().y()));
+    writer.writeAttribute("position",attrPos);
+    QString attrDim = QString::number(getWidth()).append(",").append(QString::number(getHeight()));
+    writer.writeAttribute("dimension",attrDim);
+
+    writer.writeStartElement("big_ifaces");
+    writer.writeAttribute("count",QString::number(interfaces.length()));
+    foreach(InterfaceItem* inter, interfaces){
+      writer.writeStartElement("big_iface");
+
+      writer.writeAttribute("id",QString::number(inter->getId()));
+      writer.writeAttribute("ref_name",inter->refInter->getName());
+      writer.writeAttribute("orientation",inter->getStrOrientation());
+      writer.writeAttribute("position",QString::number(inter->getPositionRatio()));
+
+      writer.writeEndElement(); //</big_iface>
+    }
+
+    writer.writeEndElement(); //</big_ifaces>
+    writer.writeEndElement(); //</bi_group>
+  }
+}
+
+QDataStream &operator <<(QDataStream &out, BoxItem &b) {
+  out.setVersion(QDataStream::Qt_4_8);
+
+  QByteArray blockData;
+  QDataStream toWrite(&blockData, QIODevice::WriteOnly);
+
+  QString refXml = ((FunctionalBlock*)b.refBlock)->getReferenceXmlFile();
+  QByteArray xmlFile = QByteArray(refXml.toStdString().c_str());
+  toWrite << xmlFile;
+
+  toWrite << b.id;
+  toWrite << (int)b.x();
+  toWrite << (int)b.y();
+  toWrite << b.boxWidth;
+  toWrite << b.boxHeight;
+  toWrite << b.getInterfaces().length();
+
+  for(int i=0; i<b.getInterfaces().length(); i++){
+    InterfaceItem *inter = b.getInterfaces().at(i);
+    toWrite << inter->getId();
+    toWrite << inter->getName();
+    toWrite << inter->getPositionRatio();
+    toWrite << inter->getOrientation();
+  }
+
+  out << blockData;
+
+  return out;
+}
+
+QDataStream &operator >>(QDataStream &in, BoxItem &b)
+{
+
+  in.setVersion(QDataStream::Qt_4_8);
+
+  int x,y,nbInter;
+
+  in >> b.id;
+  in >> x;
+  in >> y;
+
+  b.setX(x);
+  b.setY(y);
+
+  in >> b.boxWidth;
+  in >> b.boxHeight;
+  in >> nbInter;
+
+  cout << "nbInter:" << nbInter << endl;
+  for(int i=0; i<nbInter; i++){
+
+    int id, orientation;
+    double positionRatio;
+    QString name;
+
+    InterfaceItem *inter = b.getInterfaces().at(i);
+    in >> id;
+    in >> name;
+    in >> positionRatio;
+    in >> orientation;
+
+    inter->setId(id);
+    inter->setName(name);
+    inter->setPositionRatio(positionRatio);
+    inter->setOrientation(orientation);
+    inter->updatePosition();
+
+  }
+
+  return in;
+}
diff --git a/BoxItem.h b/BoxItem.h
new file mode 100644 (file)
index 0000000..74eb36a
--- /dev/null
+++ b/BoxItem.h
@@ -0,0 +1,83 @@
+#ifndef __BLOCKITEM_H__
+#define __BLOCKITEM_H__
+
+#include <iostream>
+
+#include <QtCore>
+#include <QtGui>
+
+
+#include "AbstractBoxItem.h"
+class AbstractBoxItem;
+
+class GroupItem;
+class Parameters;
+class Dispacther;
+
+#include "Exception.h"
+
+using namespace std;
+using namespace Qt;
+
+/* NOTE :
+
+  A BoxItem may represent a functional block or a group block within a group item, itslef
+  within a scene. What says what it represents is refBlock, i.e. if refBlock->isFunctionalBlock()
+  or refBlock->isGroupBlock() returns true.
+ */
+class BoxItem : public AbstractBoxItem {
+
+public:
+  BoxItem(AbstractBlock *_refBlock, Dispatcher *_dispatcher, Parameters *_params, GroupItem* parent) throw(Exception);
+  ~BoxItem();
+
+  void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget = 0);  
+
+  // getters
+  inline GroupItem *getChildGroupItem() { return childGroupItem; }
+
+  // setters
+  inline void setChildGroupItem(GroupItem* item) { childGroupItem = item; }
+
+  // testers
+  bool isBoxItem();
+
+  // others
+  void moveTo(QPointF dest);
+  void save(QXmlStreamWriter& writer);
+
+protected:
+
+  void updateMinimumSize(); // modify the minimum size
+  bool updateGeometry(ChangeType type); // modify the originPoint and the total dimension
+
+  void mousePressEvent(QGraphicsSceneMouseEvent *event);
+  void mouseReleaseEvent(QGraphicsSceneMouseEvent *event);
+  void mouseMoveEvent(QGraphicsSceneMouseEvent *event);
+  void contextMenuEvent(QGraphicsSceneContextMenuEvent *event);
+  void hoverMoveEvent( QGraphicsSceneHoverEvent *event);  
+
+private:
+
+  /* NOTE :
+   A BlockItem is always graphically within a GroupItem, inside the same scene.   
+
+   A BlockItem may also be the graphical view of a GroupBlock. In this case, there exists a child scene
+   containing a GroupItem. insideGroup atribute refers to this GroupItem and thus, may be NULL if the current
+   blockItem represents a functional block
+   */
+  GroupItem *childGroupItem;
+
+
+  friend QDataStream &operator<<(QDataStream &out, BoxItem &b);
+  friend QDataStream &operator>>(QDataStream &in, BoxItem &b);
+
+signals:
+  void itemMustBeDeleted(QGraphicsItem*);
+
+};
+
+QDataStream & operator <<(QDataStream &out, BoxItem &b);
+QDataStream & operator >>(QDataStream &in, BoxItem &b);
+
+#endif // __BLOCKITEM_H__
diff --git a/ConnectedInterface.cpp b/ConnectedInterface.cpp
new file mode 100644 (file)
index 0000000..fbfa785
--- /dev/null
@@ -0,0 +1,68 @@
+#include "ArithmeticEvaluator.h"\r
+#include "ConnectedInterface.h"\r
+#include "FunctionalBlock.h"\r
+#include "GroupBlock.h"\r
+\r
+\r
+ConnectedInterface::ConnectedInterface(AbstractBlock* _owner) : AbstractInterface(_owner) {\r
+  connectedFrom = NULL;\r
+}\r
+\r
+ConnectedInterface::ConnectedInterface(AbstractBlock* _owner, const QString& _name, const QString& _type, const QString& _width, int _direction, int _purpose, int _level) : AbstractInterface(_owner, _name, _type, _width, _direction, _purpose, _level) {\r
+  connectedFrom = NULL;\r
+}\r
+\r
+void ConnectedInterface::removeConnectedTo(ConnectedInterface *iface) {\r
+  connectedTo.removeOne(iface);\r
+}\r
+\r
+void ConnectedInterface::clearConnections() {\r
+  connectedFrom = NULL;\r
+  connectedTo.clear();\r
+}\r
+\r
+void ConnectedInterface::clearConnectedTo() {\r
+  connectedTo.clear();\r
+}\r
+\r
+bool ConnectedInterface::connectTo(ConnectedInterface *iface) {\r
+\r
+  if (canConnectTo(iface)) {\r
+    connectedTo.append(iface);\r
+    return true;\r
+  }\r
+\r
+  return false;\r
+}\r
+\r
+bool ConnectedInterface::connectFrom(ConnectedInterface *iface) {\r
+  if (canConnectFrom(iface)) {\r
+    connectedFrom = iface;\r
+    return true;\r
+  }\r
+  return false;\r
+}\r
+\r
+/* getConnectionToParentGroup() :\r
+   if an interface among connectedTo is an interface of the parent group\r
+   returns it.\r
+*/\r
+ConnectedInterface* ConnectedInterface::getConnectionToParentGroup() {\r
+  foreach(ConnectedInterface *iface, connectedTo) {\r
+    if (owner->getParent() == iface->owner) {\r
+      return iface;\r
+    }\r
+  }\r
+  return NULL;\r
+}\r
+\r
+/* getConnectionFromParentGroup() :\r
+   if connectedFrom is an interface of the parent group\r
+   returns it.\r
+*/\r
+ConnectedInterface *ConnectedInterface::getConnectionFromParentGroup() {\r
+  if ((connectedFrom != NULL) && (owner->getParent() == connectedFrom->owner)) {\r
+    return connectedFrom;\r
+  }\r
+  return NULL;\r
+}\r
diff --git a/ConnectedInterface.h b/ConnectedInterface.h
new file mode 100644 (file)
index 0000000..968a00a
--- /dev/null
@@ -0,0 +1,58 @@
+#ifndef __CONNECTEDINTERFACE_H__
+#define __CONNECTEDINTERFACE_H__
+
+#include <iostream>
+
+#include <QtCore>
+#include <QtGui>
+
+#include "AbstractInterface.h"
+class ReferenceInterface;
+
+#include "Exception.h"
+
+using namespace std;
+using namespace Qt;
+
+
+class ConnectedInterface : public AbstractInterface {
+
+public :
+
+  ConnectedInterface(AbstractBlock* _owner);
+  ConnectedInterface(AbstractBlock* _owner, const QString& _name, const QString& _type, const QString& _width, int _direction, int _purpose, int _level);
+  // getters
+  inline QList<ConnectedInterface*> getConnectedTo() { return connectedTo;}
+  inline ConnectedInterface* getConnectedFrom() { return connectedFrom;}
+
+  // setters
+
+  // testers
+  inline bool isConnectedTo(){return connectedTo.length() != 0;}
+  inline bool isConnectedFrom(){return connectedFrom != NULL;}
+  virtual bool canConnectTo(AbstractInterface* iface) = 0;
+  virtual bool canConnectFrom(AbstractInterface* iface) = 0;
+
+  // others
+  bool connectTo(ConnectedInterface* iface);
+  bool connectFrom(ConnectedInterface* iface);
+  ConnectedInterface* getConnectionToParentGroup();
+  ConnectedInterface* getConnectionFromParentGroup();
+
+  virtual AbstractInterface *clone() = 0;
+
+  void removeConnectedTo(ConnectedInterface *inter);
+
+  virtual void clearConnectedTo();
+  inline void clearConnectedFrom() { connectedFrom = NULL; }
+  virtual void clearConnections();
+  //virtual void connectionsValidation(QStack<AbstractInterface*> *interfacetoValidate, QList<AbstractInterface*> *validatedInterfaces) throw(Exception) = 0;  
+
+protected:
+  QList<ConnectedInterface*> connectedTo;
+  ConnectedInterface* connectedFrom;
+
+};
+
+
+#endif // __CONNECTEDINTERFACE_H__
diff --git a/ConnectionItem.cpp b/ConnectionItem.cpp
new file mode 100644 (file)
index 0000000..dee71ba
--- /dev/null
@@ -0,0 +1,762 @@
+#include "ConnectionItem.h"
+
+#include "Dispatcher.h"
+#include "Parameters.h"
+#include "AbstractBoxItem.h"
+#include "ConnectedInterface.h"
+#include "InterfaceItem.h"
+#include "AbstractBlock.h"
+
+//int ConnectionItem::counter = 0;
+
+ConnectionItem::ConnectionItem(InterfaceItem* _iface1,
+                               InterfaceItem* _iface2,
+                               Dispatcher* _dispatcher,
+                               Parameters* _params,
+                               QGraphicsItem *_parent) : QGraphicsItem(_parent) {
+
+
+  dispatcher = _dispatcher;
+  params = _params;
+
+  ConnectedInterface* ref1 = _iface1->refInter;
+  ConnectedInterface* ref2 = _iface2->refInter;
+  /* ref. note in .h
+     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.
+   */
+  if (ref1->getOwner() == ref2->getOwner()->getParent()) {
+
+    if (ref1->getDirection() == AbstractInterface::Input) {
+      fromInterfaceItem = _iface1;
+      toInterfaceItem = _iface2;
+    }
+    else if (ref1->getDirection() == AbstractInterface::InOut) {
+      fromInterfaceItem = _iface1;
+      toInterfaceItem = _iface2;
+    }
+    else if (ref1->getDirection() == AbstractInterface::Output) {
+      toInterfaceItem = _iface1;
+      fromInterfaceItem = _iface2;
+    }
+  }
+  else if (ref1->getOwner()->getParent() == ref2->getOwner()) {
+
+    if (ref1->getDirection() == AbstractInterface::Input) {
+      fromInterfaceItem = _iface2;
+      toInterfaceItem = _iface1;
+    }
+    else if (ref1->getDirection() == AbstractInterface::InOut) {
+      fromInterfaceItem = _iface2;
+      toInterfaceItem = _iface1;
+    }
+    else if (ref1->getDirection() == AbstractInterface::Output) {
+      toInterfaceItem = _iface2;
+      fromInterfaceItem = _iface1;
+    }
+  }
+  // NB : this case is in fact similar to the previous. Kept here for clarity
+  else if (ref1->getOwner()->getParent() == ref2->getOwner()->getParent()) {
+
+    if (ref1->getDirection() == AbstractInterface::Input) {
+      fromInterfaceItem = _iface2;
+      toInterfaceItem = _iface1;
+    }
+    else if (ref1->getDirection() == AbstractInterface::InOut) {
+      fromInterfaceItem = _iface2;
+      toInterfaceItem = _iface1;
+    }
+    else if (ref1->getDirection() == AbstractInterface::Output) {
+      toInterfaceItem = _iface2;
+      fromInterfaceItem = _iface1;
+    }
+  }
+  // adding this to interface items
+  fromInterfaceItem->addConnectionItem(this);
+  toInterfaceItem->addConnectionItem(this);
+
+  selected = false;
+  marginConn = params->arrowLineLength+params->arrowWidth;
+
+  setFlag(ItemIsSelectable);
+  setAcceptHoverEvents(true);
+  setFlag(ItemSendsGeometryChanges);
+  setCursor(Qt::PointingHandCursor);
+  setZValue(0);
+
+  setPathes();
+}
+
+
+ConnectionItem::ConnectionItem(const ConnectionItem &copy) {
+  pointFrom = copy.pointFrom;
+  pointTo = copy.pointTo;
+  interPoint1 = copy.interPoint1;
+  interPoint2 = copy.interPoint2;
+  interPoint3 = copy.interPoint3;
+  interPoint4 = copy.interPoint4;
+}
+
+ConnectionItem::~ConnectionItem() {
+}
+
+ConnectionItem::ConnectionItem() {
+}
+
+QPainterPath ConnectionItem::shape() const {
+  return pathShape;
+}
+
+QRectF ConnectionItem::boundingRect() const {
+
+  QPointF start, end;
+
+  if(pointFrom.x() < pointTo.x()){
+    start.setX(pointFrom.x()-20);
+    end.setX(pointTo.x()+20);
+  } else {
+    start.setX(pointTo.x()-20);
+    end.setX(pointFrom.x()+20);
+  }
+  if(pointFrom.y() < pointTo.y()){
+    start.setY(pointFrom.y()-20);
+    end.setY(pointTo.y()+20);
+  } else {
+    start.setY(pointTo.y()-20);
+    end.setY(pointFrom.y()+20);
+  }
+  return QRectF(start, end);
+}
+
+void ConnectionItem::paint(QPainter *painter,
+                           const QStyleOptionGraphicsItem *option,
+                           QWidget *widget) {
+
+  painter->setPen(Qt::blue);
+  if(selected){
+    painter->setPen(Qt::red);
+  }
+
+  painter->drawPath(pathPaint);
+}
+
+void ConnectionItem::addInterPoint(QPointF point) {
+
+}
+
+void ConnectionItem::setPathes() {
+
+  prepareGeometryChange();
+
+  pointFrom = fromInterfaceItem->getEndPointInGroup();
+  pointTo = toInterfaceItem->getEndPointInGroup();
+
+  int oriFrom, oriTo;
+  oriFrom = fromInterfaceItem->getOrientation();
+  oriTo = toInterfaceItem->getOrientation();
+
+/* 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;
+    }
+  }
+  double gap1 = 0.0;
+  double gap2 = 0.0;
+
+  if(oriFrom == Parameters::South) {
+
+    // FROM SOUTH TO SOUTH
+    if(oriTo == Parameters::South) {
+      computeElle(oriFrom);
+    }
+    // FROM SOUTH TO NORTH
+    else if(oriTo == Parameters::North) {
+      gap1 = pointTo.y() - pointFrom.y();
+      if (gap1 > 2*marginConn) {
+        computeStaircase(oriFrom);
+      }
+      else {
+        computeEsse(oriFrom);
+      }
+    }
+    // FROM SOUTH TO EAST OR WEST
+    else if ((oriTo == Parameters::East) || (oriTo == Parameters::West)){
+
+      gap1 = pointTo.x() - pointFrom.x();
+      if (oriTo == Parameters::West) gap1 = -gap1;
+      gap2 = pointTo.y() - pointFrom.y();
+
+      if (gap1 > 0.0) {
+        if (gap2 > 0.0) {
+          computeHookSmallEnd(oriFrom,oriTo);
+        }
+        else {
+          computeOpenRect(oriFrom,oriTo);
+        }
+      }
+      else {
+        if (gap2 >= 0.0) {
+          computeCorner(oriFrom);
+        }
+        else {
+          computeHookSmallStart(oriFrom,oriTo);
+        }
+      }
+    }
+  }
+  else if(oriFrom == Parameters::North) {
+
+    // FROM NORTH TO SOUTH
+    if(oriTo == Parameters::South) {
+      gap1 = pointFrom.y() - pointTo.y();
+      if (gap1 > 2*marginConn) {
+        computeStaircase(oriFrom);
+      }
+      else {
+        computeEsse(oriFrom);
+      }
+    }
+    // FROM NORTH TO NORTH
+    else if(oriTo == Parameters::North) {
+      computeElle(oriFrom);
+    }
+    // FROM NORTH TO EAST OR WEST
+    else if ((oriTo == Parameters::East) || (oriTo == Parameters::West)){
+
+      gap1 = pointTo.x() - pointFrom.x();
+      if (oriTo == Parameters::West) gap1 = -gap1;
+      gap2 = pointFrom.y() - pointTo.y();
+
+      if (gap1 > 0.0) {
+        if (gap2 > 0.0) {
+          computeHookSmallEnd(oriFrom,oriTo);
+        }
+        else {
+          computeOpenRect(oriFrom,oriTo);
+        }
+      }
+      else {
+        if (gap2 >= 0.0) {
+          computeCorner(oriFrom);
+        }
+        else {
+          computeHookSmallStart(oriFrom,oriTo);
+        }
+      }
+    }
+  }
+  else if(oriFrom == Parameters::East) {
+    // FROM EAST TO NORTH OR SOUTH
+    if ((oriTo == Parameters::South) || (oriTo == Parameters::North)){
+
+      gap1 = pointFrom.x() - pointTo.x();
+      gap2 = pointFrom.y() - pointTo.y();
+      if (oriTo == Parameters::North) gap2 = -gap2;
+
+      if (gap1 > 0.0) {
+        if (gap2 > 0.0) {
+          computeHookSmallStart(oriFrom,oriTo);
+        }
+        else {
+          computeOpenRect(oriFrom,oriTo);
+        }
+      }
+      else {
+        if (gap2 >= 0.0) {
+          computeCorner(oriFrom);
+        }
+        else {
+          computeHookSmallEnd(oriFrom,oriTo);
+        }
+      }
+    }
+    else if(oriTo == Parameters::East) {
+      computeElle(oriFrom);
+    }
+    else if (oriTo == Parameters::West) {
+      gap1 = pointTo.x() - pointFrom.x();
+      if (gap1 > 2*marginConn) {
+        computeStaircase(oriFrom);
+      }
+      else {
+        computeEsse(oriFrom);
+      }
+    }
+  }
+  else if (oriFrom == Parameters::West) {
+
+    // FROM WEST TO NORTH OR SOUTH
+    if ((oriTo == Parameters::South) || (oriTo == Parameters::North)){
+
+      gap1 = pointTo.x() - pointFrom.x();
+      gap2 = pointFrom.y() - pointTo.y();
+      if (oriTo == Parameters::North) gap2 = -gap2;
+
+      if (gap1 > 0.0) {
+        if (gap2 > 0.0) {
+          computeHookSmallStart(oriFrom,oriTo);
+        }
+        else {
+          computeOpenRect(oriFrom,oriTo);
+        }
+      }
+      else {
+        if (gap2 >= 0.0) {
+          computeCorner(oriFrom);
+        }
+        else {
+          computeHookSmallEnd(oriFrom,oriTo);
+        }
+      }
+    }
+    else if(oriTo == Parameters::East) {
+      gap1 = pointFrom.x() - pointTo.x();
+      if (gap1 > 2*marginConn) {
+        computeStaircase(oriFrom);
+      }
+      else {
+        computeEsse(oriFrom);
+      }
+    }
+    else if (oriTo == Parameters::West) {
+      computeElle(oriFrom);
+    }
+  }
+
+  pps.setWidth(5);
+  pathShape = pps.createStroke(pathPaint);
+}
+
+
+void ConnectionItem::computeEsse(int orientationFrom) {
+
+  //cout << "drawing an esse" << endl;
+  pathPaint = QPainterPath(pointFrom);
+  interPoints.clear();
+  double gap = marginConn;
+  if ((orientationFrom == Parameters::North)||(orientationFrom == Parameters::West)) gap = -gap;
+  QPointF p(0.0,0.0);
+
+  if ((orientationFrom == Parameters::East)||(orientationFrom == Parameters::West)) {
+    // must draw a complete esse
+    p = QPointF(pointFrom.x()+gap,pointFrom.y());
+    pathPaint.lineTo(p);
+    interPoints.append(p);
+    p = QPointF(pointFrom.x()+gap,(pointFrom.y()+pointTo.y())/2.0);
+    pathPaint.lineTo(p);
+    interPoints.append(p);
+    p = QPointF(pointTo.x()-gap,(pointFrom.y()+pointTo.y())/2.0);
+    pathPaint.lineTo(p);
+    interPoints.append(p);
+    p = QPointF(pointTo.x()-gap,pointTo.y());
+    pathPaint.lineTo(p);
+    interPoints.append(p);
+    pathPaint.lineTo(pointTo);
+  }
+  else if ((orientationFrom == Parameters::South)||(orientationFrom == Parameters::North)) {
+
+    // must draw a complete esse
+    p = QPointF(pointFrom.x(),pointFrom.y()+gap);
+    pathPaint.lineTo(p);
+    interPoints.append(p);
+    p = QPointF((pointFrom.x()+pointTo.x())/2.0,pointFrom.y()+gap);
+    pathPaint.lineTo(p);
+    interPoints.append(p);
+    p = QPointF((pointFrom.x()+pointTo.x())/2.0,pointTo.y()-gap);
+    pathPaint.lineTo(p);
+    interPoints.append(p);
+    p = QPointF(pointTo.x(), pointTo.y()-gap);
+    pathPaint.lineTo(p);
+    interPoints.append(p);
+    pathPaint.lineTo(pointTo);
+  }
+}
+
+void ConnectionItem::computeStaircase(int orientationFrom) {
+
+  pathPaint = QPainterPath(pointFrom);
+  interPoints.clear();
+  QPointF p(0.0,0.0);
+
+  if ((orientationFrom == Parameters::East)||(orientationFrom == Parameters::West)) {
+    if (pointFrom.y() == pointTo.y()) {
+      //cout << "drawing straight line" << endl;
+      pathPaint.lineTo(pointTo);
+    }
+    else  {
+      //cout << "drawing a staircase" << endl;
+      // sufficient place to draw a simple staircase
+      p = QPointF((pointFrom.x()+pointTo.x())/2.0,pointFrom.y());
+      pathPaint.lineTo(p);
+      interPoints.append(p);
+      p = QPointF((pointFrom.x()+pointTo.x())/2.0,pointTo.y());
+      pathPaint.lineTo(p);
+      interPoints.append(p);
+      pathPaint.lineTo(pointTo);
+    }
+  }
+  else if ((orientationFrom == Parameters::South)||(orientationFrom == Parameters::North)) {
+    if (pointFrom.x() == pointTo.x()) {
+      //cout << "drawing straight line" << endl;
+      pathPaint.lineTo(pointTo);
+    }
+    else {
+      //cout << "drawing a staircase" << endl;
+      // sufficient place to draw a simple staircase
+      p = QPointF(pointFrom.x(),(pointFrom.y()+pointTo.y())/2.0);
+      pathPaint.lineTo(p);
+      interPoints.append(p);
+      p = QPointF(pointTo.x(),(pointFrom.y()+pointTo.y())/2.0);
+      pathPaint.lineTo(p);
+      interPoints.append(p);
+      pathPaint.lineTo(pointTo);
+    }
+  }
+}
+
+/* drawCorner():
+
+  A Corner has the following shape :
+  |
+  |__
+
+*/
+void ConnectionItem::computeCorner(int orientationFrom) {
+
+  pathPaint = QPainterPath(pointFrom);
+  interPoints.clear();
+  QPointF p(0.0,0.0);
+  //cout << "drawing a corner" << endl;
+
+  if ((orientationFrom == Parameters::East)||(orientationFrom == Parameters::West)) {
+    p = QPointF(pointTo.x(),pointFrom.y());
+    pathPaint.lineTo(p);
+    interPoints.append(p);
+    pathPaint.lineTo(pointTo);
+  }
+  else if ((orientationFrom == Parameters::South)||(orientationFrom == Parameters::North)) {
+    p = QPointF(pointFrom.x(),pointTo.y());
+    pathPaint.lineTo(p);
+    interPoints.append(p);
+    pathPaint.lineTo(pointTo);
+  }
+}
+
+/* drawOpenRect():
+
+  A OpenRect has the following shape :
+  __
+  |
+  |_|
+*/
+void ConnectionItem::computeOpenRect(int orientationFrom, int orientationTo) {
+  pathPaint = QPainterPath(pointFrom);
+  interPoints.clear();
+  QPointF p(0.0,0.0);
+  double gap1 = marginConn;
+  double gap2 = marginConn;
+  //cout << "drawing an OpenRect" << endl;
+
+  if ((orientationFrom == Parameters::East)||(orientationFrom == Parameters::West)) {
+    if (orientationFrom == Parameters::West) {
+      gap1 = -gap1;
+    }
+    if (orientationTo == Parameters::North) {
+      gap2 = -gap2;
+    }
+    p = QPointF(pointFrom.x()+gap1,pointFrom.y());
+    pathPaint.lineTo(p);
+    interPoints.append(p);
+    p = QPointF(pointFrom.x()+gap1,pointTo.y()+gap2);
+    pathPaint.lineTo(p);
+    interPoints.append(p);
+    p = QPointF(pointTo.x(),pointTo.y()+gap2);
+    pathPaint.lineTo(p);
+    interPoints.append(p);
+    pathPaint.lineTo(pointTo);
+
+  }
+  else if ((orientationFrom == Parameters::South)||(orientationFrom == Parameters::North)) {
+    if (orientationFrom == Parameters::North) {
+      gap1 = -gap1;
+    }
+    if (orientationTo == Parameters::West) {
+      gap2 = -gap2;
+    }
+    p = QPointF(pointFrom.x(),pointFrom.y()+gap1);
+    pathPaint.lineTo(p);
+    interPoints.append(p);
+    p = QPointF(pointTo.x()+gap2,pointFrom.y()+gap1);
+    pathPaint.lineTo(p);
+    interPoints.append(p);
+    p = QPointF(pointTo.x()+gap2,pointTo.y());
+    pathPaint.lineTo(p);
+    interPoints.append(p);
+    pathPaint.lineTo(pointTo);
+  }
+}
+
+/* drawHookSmallEnd():
+
+  A Hook has the following shape :
+  _
+   |
+   |_|
+   Its end has always a size of marginConn
+*/
+void ConnectionItem::computeHookSmallEnd(int orientationFrom, int orientationTo) {
+  pathPaint = QPainterPath(pointFrom);
+  interPoints.clear();
+  QPointF p(0.0,0.0);
+  double gap = marginConn;
+  //cout << "drawing a Hook with small end" << endl;
+
+  if ((orientationFrom == Parameters::East)||(orientationFrom == Parameters::West)) {
+
+    if (orientationTo == Parameters::North) gap = -gap;
+
+    p = QPointF((pointFrom.x()+pointTo.x())/2.0,pointFrom.y());
+    pathPaint.lineTo(p);
+    interPoints.append(p);
+    p = QPointF((pointFrom.x()+pointTo.x())/2.0,pointTo.y()+gap);
+    pathPaint.lineTo(p);
+    interPoints.append(p);
+    p = QPointF(pointTo.x(),pointTo.y()+gap);
+    pathPaint.lineTo(p);
+    interPoints.append(p);
+    pathPaint.lineTo(pointTo);
+
+  }
+  else if ((orientationFrom == Parameters::South)||(orientationFrom == Parameters::North)) {
+
+    if (orientationTo == Parameters::West) gap = -gap;
+
+    p = QPointF(pointFrom.x(),(pointFrom.y()+pointTo.y())/2.0);
+    pathPaint.lineTo(p);
+    interPoints.append(p);
+    p = QPointF(pointTo.x()+gap,(pointFrom.y()+pointTo.y())/2.0);
+    pathPaint.lineTo(p);
+    interPoints.append(p);
+    p = QPointF(pointTo.x()+gap,pointTo.y());
+    pathPaint.lineTo(p);
+    interPoints.append(p);
+    pathPaint.lineTo(pointTo);
+  }
+}
+
+/* drawHookSmallStart():
+
+  A Hook has the following shape :
+  _
+   |
+   |_|
+   Its start has always a size of marginConn
+*/
+void ConnectionItem::computeHookSmallStart(int orientationFrom, int orientationTo) {
+  pathPaint = QPainterPath(pointFrom);
+  interPoints.clear();
+  QPointF p(0.0,0.0);
+  double gap = marginConn;
+  //cout << "drawing a Hook with small start" << endl;
+
+  if ((orientationFrom == Parameters::East)||(orientationFrom == Parameters::West)) {
+
+    if (orientationFrom == Parameters::West) gap = -gap;
+
+    p = QPointF(pointFrom.x()+gap,pointFrom.y());
+    pathPaint.lineTo(p);
+    interPoints.append(p);
+    p = QPointF(pointFrom.x()+gap,(pointFrom.y()+pointTo.y())/2.0);
+    pathPaint.lineTo(p);
+    interPoints.append(p);
+    p = QPointF(pointTo.x(),(pointFrom.y()+pointTo.y())/2.0);
+    pathPaint.lineTo(p);
+    interPoints.append(p);
+    pathPaint.lineTo(pointTo);
+  }
+  else if ((orientationFrom == Parameters::South)||(orientationFrom == Parameters::North)) {
+
+    if (orientationFrom == Parameters::North) gap = -gap;
+
+    p = QPointF(pointFrom.x(),pointFrom.y()+gap);
+    pathPaint.lineTo(p);
+    interPoints.append(p);
+    p = QPointF((pointFrom.x()+pointTo.x())/2.0,pointFrom.y()+gap);
+    pathPaint.lineTo(p);
+    interPoints.append(p);
+    p = QPointF((pointFrom.x()+pointTo.x())/2.0,pointTo.y());
+    pathPaint.lineTo(p);
+    interPoints.append(p);
+    pathPaint.lineTo(pointTo);
+  }
+}
+
+/* drawElle():
+
+  An Elle has the following shape :
+  |
+  |_|
+
+*/
+void ConnectionItem::computeElle(int orientationFrom) {
+
+  pathPaint = QPainterPath(pointFrom);
+  interPoints.clear();
+  QPointF p(0.0,0.0);
+  double x;
+  double y;
+  switch(orientationFrom){
+  case Parameters::North :
+    if(pointFrom.y() < pointTo.y()) {
+      y = pointFrom.y()-marginConn;
+    }
+    else {
+      y = pointTo.y()-marginConn;
+    }
+    p = QPointF(pointFrom.x(),y);
+    pathPaint.lineTo(p);
+    interPoints.append(p);
+    p = QPointF(pointTo.x(),y);
+    pathPaint.lineTo(p);
+    interPoints.append(p);
+    pathPaint.lineTo(pointTo);
+    break;
+  case Parameters::South :
+    if(pointFrom.y() > pointTo.y()) {
+      y = pointFrom.y()+marginConn;
+    }
+    else {
+      y = pointTo.y()+marginConn;
+    }
+    p = QPointF(pointFrom.x(),y);
+    pathPaint.lineTo(p);
+    interPoints.append(p);
+    p = QPointF(pointTo.x(),y);
+    pathPaint.lineTo(p);
+    interPoints.append(p);
+    pathPaint.lineTo(pointTo);
+    break;
+  case Parameters::West :
+    if(pointFrom.x() < pointTo.x()) {
+      x = pointFrom.x()-marginConn;
+    }
+    else {
+      x = pointTo.x()-marginConn;
+    }
+    p = QPointF(x, pointFrom.y());
+    pathPaint.lineTo(p);
+    interPoints.append(p);
+    p = QPointF(x, pointTo.y());
+    pathPaint.lineTo(p);
+    interPoints.append(p);
+    pathPaint.lineTo(pointTo);
+    break;
+  case Parameters::East :
+    if(pointFrom.x() > pointTo.x()) {
+      x = pointFrom.x()+marginConn;
+    }
+    else {
+      x = pointTo.x()+marginConn;
+    }
+    p = QPointF(x, pointFrom.y());
+    pathPaint.lineTo(p);
+    interPoints.append(p);
+    p = QPointF(x, pointTo.y());
+    pathPaint.lineTo(p);
+    interPoints.append(p);
+    pathPaint.lineTo(pointTo);
+    break;
+  }
+}
+
+void ConnectionItem::setSelected(bool selected) {
+  this->selected = selected;
+  if(selected){
+    setZValue(50);
+  } else {
+    setZValue(0);
+  }
+}
+
+void ConnectionItem::mousePressEvent(QGraphicsSceneMouseEvent *event) {
+  QGraphicsItem::mousePressEvent(event);
+  setZValue(zValue()+100);  
+  setSelected(!selected);
+  update(boundingRect());
+}
+
+void ConnectionItem::mouseReleaseEvent(QGraphicsSceneMouseEvent *event) {
+  QGraphicsItem::mouseReleaseEvent(event);
+  setZValue(zValue()-100);
+}
+
+void ConnectionItem::mouseMoveEvent(QGraphicsSceneMouseEvent *event) {
+  QGraphicsItem::mouseMoveEvent(event);
+}
+
+void ConnectionItem::contextMenuEvent(QGraphicsSceneContextMenuEvent * event) {
+  QMenu menu;
+  QAction* removeAction = menu.addAction("Remove");
+  QAction * selectedAction= menu.exec(event->screenPos());
+
+  if(selectedAction == removeAction){
+    dispatcher->removeConnection(this);
+    dispatcher->removeUselessGroupInterfaces();
+  }
+}
+
+void ConnectionItem::prepareChange() {
+  prepareGeometryChange();
+}
+
+QDataStream &operator <<(QDataStream &out, ConnectionItem &c) {
+  out.setVersion(QDataStream::Qt_4_8);
+
+  QByteArray connData;
+  QDataStream toWrite(&connData, QIODevice::WriteOnly);
+
+  toWrite << c.id;
+  toWrite << c.getFromInterfaceItem()->getId();
+  toWrite << c.getToInterfaceItem()->getId();
+
+  out << connData;
+
+  return out;
+}
+
+QDataStream &operator >>(QDataStream &in, ConnectionItem &c) {
+  in.setVersion(QDataStream::Qt_4_8);
+
+  return in;
+}
diff --git a/ConnectionItem.h b/ConnectionItem.h
new file mode 100644 (file)
index 0000000..567a31d
--- /dev/null
@@ -0,0 +1,107 @@
+#ifndef __CONNECTIONITEM_H__
+#define __CONNECTIONITEM_H__
+
+#include <iostream>
+
+#include <QtCore>
+#include <QtGui>
+#include <QGraphicsItem>
+
+class Dispatcher;
+class Parameters;
+class InterfaceItem;
+
+using namespace std;
+using namespace Qt;
+
+/* NOTES :
+
+   A connection item represent a graphical link between two interface items.
+   Even if it links two in/out interfaces, it is always oriented.
+   The orientation depends on the type and direction of linked interfaces :
+
+   If interfaces are owned by blocks (group or func) that are within the same
+   parent group, then src must be an output, and dest an input, or both are in/out
+   and src/dest may be interchanged.
+
+   If one interface I1 is owend by a block, and the other I2 by the parent group of that block,
+   then they have the same direction. If this direction is input, then src = I2 and dest = I1,
+   if it is output, then src = I1, dest = I2, and if it is in/out, no order matters.
+
+   In order to simplify other methods, the constructor of ConnectionItem
+   checks these cases in order to retrieve the good src and dest if they are
+   not provided in the good order.
+
+ */
+class ConnectionItem : public QGraphicsItem {
+
+public:
+
+  ConnectionItem(InterfaceItem* _iface1,
+                 InterfaceItem* _iface2,
+                 Dispatcher* _dispatcher,
+                 Parameters* _params,
+                 QGraphicsItem* _parent);
+  ConnectionItem (const ConnectionItem & copy);
+  ConnectionItem();
+  ~ConnectionItem();
+
+  QRectF boundingRect() const;
+  QPainterPath shape() const;
+
+  void prepareChange();
+
+  inline InterfaceItem* getToInterfaceItem(){ return toInterfaceItem; }
+  inline void setToInterfaceItem(InterfaceItem *iface){ toInterfaceItem = iface; }
+  inline InterfaceItem* getFromInterfaceItem(){ return fromInterfaceItem; }
+  inline void setFromInterfaceItem(InterfaceItem* iface){ fromInterfaceItem = iface; }
+  inline int getId(){ return id; }
+  inline void setId(int id){ this->id = id; }
+  inline bool isSelected() { return selected; }
+  void setSelected(bool selected);
+
+  void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget = 0);
+  void setPathes();
+  void addInterPoint(QPointF point);
+
+  static int counter;
+
+protected:
+  void mousePressEvent(QGraphicsSceneMouseEvent *event);
+  void mouseReleaseEvent(QGraphicsSceneMouseEvent *event);
+  void mouseMoveEvent(QGraphicsSceneMouseEvent *event);
+  void contextMenuEvent(QGraphicsSceneContextMenuEvent *event);
+
+private:
+
+  QPointF pointFrom;
+  QPointF pointTo;
+  QList<QPointF> interPoints;
+  QPointF interPoint1;
+  QPointF interPoint2;
+  QPointF interPoint3;
+  QPointF interPoint4;
+
+  QPainterPath pathPaint;
+  QPainterPath pathShape;
+  QPainterPathStroker pps;
+  Dispatcher* dispatcher;
+  Parameters* params;
+  InterfaceItem* fromInterfaceItem;
+  InterfaceItem* toInterfaceItem;
+  bool selected;
+  int id;
+  int marginConn;
+  void computeEsse(int orientationFrom);
+  void computeStaircase(int orientationFrom);
+  void computeHookSmallEnd(int orientationFrom, int orientationTo);
+  void computeHookSmallStart(int orientationFrom, int orientationTo);
+  void computeOpenRect(int orientationFrom, int orientationTo);
+  void computeElle(int orientationFrom);
+  void computeCorner(int orientationFrom);
+
+  friend QDataStream &operator << (QDataStream &out, ConnectionItem &c);
+  friend QDataStream &operator >> (QDataStream &in, ConnectionItem &c);
+};
+
+#endif //
diff --git a/Dispatcher.cpp b/Dispatcher.cpp
new file mode 100644 (file)
index 0000000..a85b942
--- /dev/null
@@ -0,0 +1,832 @@
+#include "Dispatcher.h"
+#include "Parameters.h"
+#include "MainWindow.h"
+
+#include "Graph.h"
+#include "ReferenceBlock.h"
+#include "GroupBlock.h"
+#include "FunctionalBlock.h"
+
+#include "ConnectedInterface.h"
+#include "ReferenceInterface.h"
+#include "GroupInterface.h"
+#include "FunctionalInterface.h"
+
+#include "GroupWidget.h"
+#include "GroupScene.h"
+#include "GroupItem.h"
+#include "BoxItem.h"
+#include "InterfaceItem.h"
+#include "ConnectionItem.h"
+
+#include "BlockLibraryWidget.h"
+#include "BlockLibraryTree.h"
+
+#include "InterfacePropertiesWindow.h"
+
+
+Dispatcher::Dispatcher(Parameters* _params, MainWindow* _window) {
+  params = _params;
+  mainWindow =_window;
+  params->setDispatcher(this);
+  currentGroup = NULL;
+  topGroup = NULL;    
+}
+
+GroupWidget *Dispatcher::loadProject(const QString& filename) {
+
+  QDomElement root;
+  try {
+    root = params->openProjectFile(filename);
+  }
+  catch(Exception err) {
+    return NULL;
+  }
+
+  // creating the top widget/scene
+  topGroup = new GroupWidget(NULL,this,params);
+  currentGroup = topGroup;
+  // getting the newly created scene
+  GroupScene *scene = topGroup->getScene();
+  params->setTopScene(scene);
+  params->setCurrentScene(scene);
+
+  try {   
+    params->loadProject(root);
+  }
+  catch(Exception e){
+    cerr << qPrintable(e.getDefaultMessage()) << endl;
+    cerr << "Aborting ..." << endl;
+    // TO DO : deleteting topGroup and all
+    return NULL;
+  }
+
+  return topGroup;
+}
+
+void Dispatcher::closeCurrentProject() {
+
+  foreach(GroupWidget* win, groupList) {
+    win->deleteLater();
+  }
+  params->destroyGraph();
+}
+
+bool Dispatcher::connect(InterfaceItem *iface1, InterfaceItem *iface2) {
+
+  ConnectedInterface* ref1 = iface1->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);
+  }
+  if (ref2->canConnectTo(ref1)) {
+    ok2 = ref2->connectTo(ref1);
+    ok2 = ok2 & ref1->connectFrom(ref2);
+  }
+  if ((ok1 == true) || (ok2 == true)) {
+
+    iface1->getOwner()->getScene()->createConnectionItem(iface1,iface2);
+
+    unselectAllItems();
+    params->unsaveModif = true;
+    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()) {
+    block->setSelected(false);
+    block->setCurrentInterface(NULL);
+  }
+  scene->unselecteInterfaces();
+  scene->update();
+}
+
+void Dispatcher::setCurrentGroupWidget(GroupWidget *win){
+  win->setFocus();
+  win->changeConnectionMode(-1);
+  currentGroup = win;
+  params->setCurrentScene(win->getScene());
+}
+
+void Dispatcher::changeConnectionMode(int mode){
+
+  /*
+  foreach(GroupWidget* win, groupList){
+
+    QToolButton* buttonNewConnection = win->getButtonNewConnection();
+
+    QPalette pal = buttonNewConnection->palette();
+
+    if(mode == -1){
+      if(params->sceneMode != Parameters::EditOnConnection){
+        params->sceneMode = Parameters::EditOnConnection;
+        pal.setColor(QPalette::Button, QColor(Qt::lightGray));
+      } else {
+        params->sceneMode = Parameters::EditNoOperation;
+        pal.setColor(QPalette::Button, QColor("#edeceb"));
+      }
+    }
+    else if(mode == Parameters::EditOnConnection){
+      params->sceneMode = Parameters::EditOnConnection;
+      pal.setColor(QPalette::Button, QColor(Qt::lightGray));
+    }
+    else {
+      params->sceneMode = Parameters::EditNoOperation;
+      pal.setColor(QPalette::Button, QColor("#edeceb"));
+    }
+    unselectAllInterfaces();
+
+    buttonNewConnection->setAutoFillBackground(true);
+    buttonNewConnection->setPalette(pal);
+    buttonNewConnection->update();
+  }
+  */
+}
+
+void Dispatcher::rename(AbstractBoxItem *item){
+
+  bool ok;
+  QString text = QInputDialog::getText(NULL, "Rename an element",
+                                       "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);
+        }
+      }
+    }
+    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);
+    }
+  }
+}
+
+void Dispatcher::rename(InterfaceItem *item){
+  bool ok;
+  QString text = QInputDialog::getText(NULL, "Rename an interface",
+                                       "New name:", QLineEdit::Normal,
+                                       item->refInter->getName(), &ok);
+
+  /* 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
+
+   */
+  if(ok && !text.isEmpty() && text.length() < 30) {
+    if (item->refInter->getOwner()->isGroupBlock()) {
+      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);
+  }
+}
+
+void Dispatcher::duplicateBlock(BoxItem *item){
+
+  GroupScene *scene = params->getCurrentScene();
+  AbstractBlock* block = item->getRefBlock();  
+  AbstractBlock *newBlock;
+
+  // only duplicate functional blocks
+  if(block->isFunctionalBlock()) {
+
+    // adding to the model
+    FunctionalBlock* funBlock = (FunctionalBlock*)block;
+    newBlock = params->duplicateFunctionalBlock(funBlock);
+    // adding to the view
+    scene->createBlockItem(newBlock);
+
+    params->unsaveModif = true;
+  }
+}
+
+void Dispatcher::duplicateInterface(InterfaceItem *item){
+  AbstractInterface *refI = item->refInter;
+  if (! refI->isFunctionalInterface()) return;
+
+  AbstractBlock *refB = refI->getOwner();
+  if(! refB->isFunctionalBlock()) return;
+
+  FunctionalInterface* iface = (FunctionalInterface*)refI;
+  AbstractInterface *otherRef = iface->clone();
+  if (otherRef == 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);
+}
+
+
+void Dispatcher::addBlock(int idCategory, int idBlock) {
+
+  GroupScene *scene = params->getCurrentScene();
+  FunctionalBlock* newOne = params->addFunctionalBlock(idCategory, idBlock);  
+  scene->createBlockItem(newOne);
+}
+
+
+GroupWidget *Dispatcher::createTopScene(){
+
+  // creating the model part of the group
+  Graph* graph = params->createGraph();
+  GroupBlock *refBlock = graph->getTopGroup();
+
+  // creating a fake and not connected interface
+  //AbstractInterface* iface = new GroupInterface(refBlock,"grp_iface",AbstractInterface::Input,AbstractInterface::Top);
+
+  // creating the group widget
+  topGroup = new GroupWidget(NULL,this,params);
+  currentGroup = topGroup;
+  // getting the newly created scene
+  GroupScene *scene = topGroup->getScene();
+  params->setTopScene(scene);
+  params->setCurrentScene(scene);
+  // creating the view part of the group
+  GroupItem *group = new GroupItem(NULL,refBlock,this,params);
+
+  // adding the fake interface to the top group item
+  //InterfaceItem* item = new InterfaceItem(0.0 , Parameters::West, (ConnectedInterface*)iface, group, params);
+  //group->addInterface(item,true);
+
+  scene->setGroupItem(group);
+
+  return topGroup;
+}
+
+GroupWidget *Dispatcher::createChildScene(GroupWidget* parentWidget, BoxItem *upperItemOfGroupItem) {
+
+  GroupBlock* parentBlock = 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");
+  // 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();
+  // affecting group item to the scene
+  scene->setGroupItem(groupItem);
+
+  return group;
+}
+
+void Dispatcher::showRaiseWindow(AbstractBoxItem *item) {
+  GroupWidget* win = item->getScene()->getGroupWindow();
+  if (win->isTopGroup()) {
+    mainWindow->show();
+    mainWindow->raise();
+  }
+  else {
+    win->show();
+    win->raise();
+  }
+  currentGroup = win;
+  params->setCurrentScene(currentGroup->getScene());
+}
+
+void Dispatcher::showRstClkInter(AbstractBoxItem *item) {
+
+  item->setRstClkVisible(!item->isRstClkVisible());
+  item->resetInterfacesPosition();
+
+  item->getScene()->updateConnectionItemsShape();
+}
+
+void Dispatcher::addNewFullGroup() {
+
+#ifdef DEBUG_INCLFUN
+
+  QList<BlockItem*> listBlocks = params->getCurrentScene()->getSelectedBlocks(); //selected blocks in the current scene
+  QList<AbstractBlock*> listAbstractBlocks;   //abstract blocks in the group
+  QList<ConnectionItem *> connections = params->getCurrentScene()->getConnectionItems();
+
+  /* What must be done:
+     1 - creating a new GroupBlock
+     2 - moving the selected blocks from the current GroupBlock to the new GroupBlock
+     3 - creating a BlockItem that references the new GroupBlock
+     4 - creating a new GroupWidget
+     5 - creating a new GroupItem added to the scene of the GroupWidget
+
+   */
+
+  /* step 1 : creating new GroupBlock that will have as a parent the GroupBlock
+     associated to the GroupItem of the current scene
+   */
+  GroupBlock* parentBlock = params->getCurrentScene()->getGroupItem()->getRefBlock();
+  GroupBlock* newGroupBlock = new GroupBlock(parentBlock);
+  /* step 2: moving selected blocks */
+  foreach(BlockItem* blockItem, listBlocks) {
+    parentBlock->removeBlock(blockItem->getRefBlock());
+    newGroupBlock->addBlock(blockItem->getRefBlock());
+  }
+
+  GroupItem *parent = currentGroup->getScene()->getGroupItem();
+  GroupBlock *groupBlock = new GroupBlock(((GroupBlock*)parent->getRefBlock()),params->currentWindow);
+  BlockItem *blockItem = new BlockItem(params->getCurrentScene()->getGroupItem(),groupBlock,this,params);
+  GroupItem *groupItem = new GroupItem(blockItem,groupBlock,this,params);
+
+  //create the new window
+  GroupWidget* win = new GroupWidget(this,params);
+  win->getScene()->setGroupItem(groupItem);
+  win->getScene()->addItem(groupItem);
+  ((GroupBlock*)groupItem->getRefBlock())->setWindow(win);
+  params->addWindow(win);
+  win->show();
+
+  //add the new group
+  params->getCurrentScene()->addBlockItem(blockItem);
+  params->getCurrentScene()->addItem(blockItem);
+  ((GroupItem*)params->getCurrentScene()->getGroupItem())->addBlockItem(blockItem);
+
+  //replace selected blocks in the group
+  foreach(AbstractBoxItem *block, listBlocks){
+    ((GroupItem*)block->getParentItem())->removeBlockItem(block);
+    ((GroupBlock*)block->getParentItem()->getRefBlock())->removeBlock(block->getRefBlock());
+    params->getCurrentScene()->removeItem(block);
+    params->getCurrentScene()->removeBlockItem(block);
+
+    groupBlock->addBlock(block->getRefBlock());
+    listAbstractBlocks.append(block->getRefBlock());
+
+    block->setUpperItem(groupItem);
+    groupItem->addBlockItem(block);
+    win->getScene()->addItem(block);
+    win->getScene()->addBlockItem(block);
+  }
+
+  //replace connection between selected blocks in the group
+  foreach(ConnectionItem *conn, connections){
+    if(listBlocks.contains(conn->getFromInterfaceItem()->getOwner())){
+      if(listBlocks.contains(conn->getToInterfaceItem()->getOwner())){
+        parent->removeConnection(conn);
+        params->getCurrentScene()->removeItem(conn);
+
+        groupItem->addConnection(conn);
+        win->getScene()->addItem(conn);
+      }
+    }
+  }
+
+  //create new interfaces and connections for the new group
+  foreach(AbstractBoxItem *block, listBlocks){
+    foreach(InterfaceItem *inter, block->getInterfaces()){
+      cout << "inter : " << inter->getName().toStdString() << endl;
+      if(inter->refInter->getConnectedFrom() != NULL && inter->refInter->getDirection() == AbstractInterface::Input){
+        cout << "connected from non null" << endl;
+        if(!listAbstractBlocks.contains(inter->refInter->getConnectedFrom()->getOwner())){
+
+          AbstractInterface *iface = inter->refInter->clone(0);
+          iface->setName(iface->getName()+"_group");
+          groupBlock->addInterface(iface);
+
+          InterfaceItem *ifaceItem = new InterfaceItem(0,Parameters::East,iface,blockItem,params);
+          blockItem->addInterface(ifaceItem);
+          blockItem->resetInterfacesPosition();
+
+          InterfaceItem *ifaceGroupItem = new InterfaceItem(0,Parameters::West,iface,groupItem,params);
+          groupItem->addInterface(ifaceGroupItem);
+          groupItem->resetInterfacesPosition();
+          foreach(ConnectionItem* conn, currentGroup->getScene()->getInterfaceConnections(inter)){
+            if(conn->getToInterfaceItem() == inter){
+              conn->setToInterfaceItem(ifaceItem);
+              ifaceItem->refInter->setConnectedFrom(NULL);
+              conn->getFromInterfaceItem()->refInter->clearConnectedTo();
+              connect(ifaceItem,conn->getFromInterfaceItem());
+            }
+          }
+          params->setCurrentWindow(win);
+
+          inter->refInter->setConnectedFrom(NULL);
+          ifaceGroupItem->refInter->clearConnectedTo();
+          connect(inter,ifaceGroupItem);
+          params->setCurrentWindow(mainWindow);
+        }
+      }
+
+      if(!inter->refInter->getConnectedTo().isEmpty() && inter->refInter->getDirection() == AbstractInterface::Output){
+        cout << "connected to non null" << endl;
+        foreach(AbstractInterface *iface, inter->refInter->getConnectedTo()){
+          if(!listAbstractBlocks.contains(iface->getOwner())){
+
+            AbstractInterface *iface = inter->refInter->clone(0);
+            iface->setName(iface->getName()+"_group");
+            groupBlock->addInterface(iface);
+
+            InterfaceItem *ifaceItem = new InterfaceItem(0,Parameters::East,iface,blockItem,params);
+            blockItem->addInterface(ifaceItem);
+            blockItem->resetInterfacesPosition();
+
+            foreach(ConnectionItem* conn, currentGroup->getScene()->getInterfaceConnections(inter)){
+              if(conn->getFromInterfaceItem() == inter){
+                conn->setFromInterfaceItem(ifaceItem);
+                iface->addConnectedTo(conn->getToInterfaceItem()->refInter);
+                conn->getToInterfaceItem()->refInter->setConnectedFrom(iface);
+              }
+            }
+
+            InterfaceItem *ifaceGroupItem = new InterfaceItem(0,Parameters::East,iface,groupItem,params);
+            groupItem->addInterface(ifaceGroupItem);
+            groupItem->resetInterfacesPosition();
+            inter->refInter->clearConnectedTo();
+            ifaceGroupItem->refInter->setConnectedFrom(NULL);
+            connect(ifaceGroupItem,inter);
+          }
+        }
+      }
+    }
+  }
+
+  //update window
+
+  parent->updateShape();
+  currentGroup->getScene()->updateConnectionItemsShape();
+  currentGroup = win;
+  groupItem->updateShape();
+  win->getScene()->updateConnectionItemsShape();
+  groupItem->update(groupItem->boundingRect());
+
+#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();
+
+  removeConnections(item);
+
+  //récupérer l'objet
+  group->removeBlock(block);
+
+  //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;
+        }
+      }
+    }
+  }
+
+  delete block;
+
+  //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;
+
+  ((GroupItem *)scene->getGroupItem())->updateShape();
+
+  params->updateToolbar();
+  params->unsaveModif = true;
+
+#endif
+}
+
+void Dispatcher::removeAllBlockConnections(AbstractBoxItem *block) {
+
+  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){
+      removeConnection(conn);
+    }
+  }
+  scene->getGroupItem()->updateInterfacesAndConnections();
+}
+
+void Dispatcher::removeConnection(ConnectionItem *conn) {
+
+  GroupScene *scene = params->getCurrentScene();
+  GroupItem* currentGroup = scene->getGroupItem();
+
+  conn->getFromInterfaceItem()->unconnectTo(conn->getToInterfaceItem());  
+
+  scene->removeConnectionItem(conn);
+  delete conn;
+
+  currentGroup->updateInterfacesAndConnections();
+  params->unsaveModif = true;
+}
+
+void Dispatcher::removeUselessGroupInterfaces() {
+
+  GroupScene *scene = params->getCurrentScene();
+  GroupItem* currentGroup = scene->getGroupItem();
+
+  foreach(InterfaceItem *inter, currentGroup->getInterfaces()) {
+    if(inter->refInter->getConnectedTo().length() == 0) {
+      // NB : remove from view also remove from model
+      currentGroup->removeInterface(inter);           
+    }
+  }
+  scene->updateConnectionItemsShape();
+}
+
+void Dispatcher::showBlocksLibrary(){
+  cout << "showing block library" << endl;
+  mainWindow->getLibrary()->show();
+  mainWindow->getLibrary()->raise();
+}
+
+void Dispatcher::showProperties(InterfaceItem *inter)
+{
+  new InterfacePropertiesWindow(inter);
+}
+
+/* connectInterToGroup() :
+   The only way for a block (functional of group) within a GroupItem to be connected
+   to the latter is to right-click on one of its interfaces and to choose "connect to group".
+   That action will create a new InterfaceItem on the GroupItem and a connectionItem between the
+   interfaces.
+*/
+void Dispatcher::connectInterToGroup(InterfaceItem *item){
+
+  // getting the GroupBlock and GroupItem that are parent of the block that owns item
+  ConnectedInterface *refInter = item->refInter;
+  GroupBlock* parentBlock = AB_TO_GRP(refInter->getOwner()->getParent());
+  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());
+  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 interface in the current scene model, and connection item
+  InterfaceItem *groupIfaceItem = new InterfaceItem(0,item->getOrientation(),groupInter,parentItem,params);
+  parentItem->addInterface(groupIfaceItem,true);
+
+  parentItem->getScene()->createConnectionItem(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);
+  }
+
+
+  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->clearConnectedTo();
+    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::removeGroupInterface(InterfaceItem *item) {
+  static QString fctName = "Dispatcher::removeGroupInterface()";
+#ifdef DEBUG_FCTNAME
+  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();
+   */
+  ConnectionItem* conn = item->connections.at(0);
+  if (conn->getFromInterfaceItem() == item) {
+    disconnectInterFromGroup(conn->getToInterfaceItem());
+  }
+  else {
+    disconnectInterFromGroup(conn->getFromInterfaceItem());
+  }
+}
+
+GroupScene* Dispatcher::searchSceneById(int id) {
+  foreach(GroupWidget *group, groupList){
+    if(group->getScene()->getId() == id)
+      return group->getScene();
+  }
+  cout << "search scene by id :" << id << " :: not found..." << endl;
+  return NULL;
+}
+
+GroupItem *Dispatcher::searchGroupItemById(int id) {
+  foreach(GroupWidget *group, groupList) {
+    GroupScene* scene = group->getScene();
+    if (scene->getGroupItem()->getId() == id) return scene->getGroupItem();
+  }
+  cout << "search GroupItem by id :" << id << " :: not found..." << endl;
+  return NULL;
+}
+
+BoxItem *Dispatcher::searchBlockItemById(int id) {
+  foreach(GroupWidget *group, groupList) {
+
+    GroupScene* scene = group->getScene();
+    foreach(BoxItem *item, scene->getBlockItems()){
+      if(item->getId() == id){
+          return item;
+      }
+    }
+  }
+  cout << "search BlockItem by id :" << id << " :: not found..." << endl;
+  return NULL;
+}
+
+InterfaceItem* Dispatcher::searchInterfaceItemById(int id) {
+
+  foreach(GroupWidget *group, groupList) {
+
+    GroupScene* scene = group->getScene();
+
+    foreach(InterfaceItem *item, scene->getGroupItem()->getInterfaces()){
+      if(item->getId() == id){
+        return item;
+      }
+    }
+    foreach(BoxItem *block, scene->getBlockItems()){
+      foreach(InterfaceItem *item, block->getInterfaces()){
+        if(item->getId() == id){
+          return item;
+        }
+      }
+    }
+  }
+  cout << "search interface by id :" << id << " :: not found..." << endl;
+  return NULL;
+}
+
diff --git a/Dispatcher.h b/Dispatcher.h
new file mode 100644 (file)
index 0000000..4475518
--- /dev/null
@@ -0,0 +1,89 @@
+#ifndef __DISPATCHER_H__
+#define __DISPATCHER_H__
+
+#include <iostream>
+
+#include <QtCore>
+#include <QtGui>
+#include <QtWidgets>
+
+class Graph;
+class Parameters;
+class MainWindow;
+class GroupWidget;
+class GroupScene;
+class AbstractBoxItem;
+class GroupItem;
+class BoxItem;
+class ConnectionItem;
+class InterfaceItem;
+
+
+
+using namespace std;
+using namespace Qt;
+
+class Dispatcher {
+
+public:
+  Dispatcher(Parameters* _params,             
+             MainWindow* _window);
+
+  GroupWidget* loadProject(const QString& filename);
+
+  inline int getNumberOfScenes() { return groupList.length(); }
+  bool connect(InterfaceItem *iface1, InterfaceItem *iface2);
+  void checkSelection();
+  void unselectAllItems(int direction=0);
+  void setCurrentGroupWidget(GroupWidget *win);
+  void changeConnectionMode(int mode = -1);
+  void rename(AbstractBoxItem* item);
+  void rename(InterfaceItem* item);
+  GroupWidget* createTopScene();
+  GroupWidget* createChildScene(GroupWidget* parentWidget, BoxItem* upperItemOfGroupItem = NULL);
+  void showRaiseWindow(AbstractBoxItem *item);
+  void showRstClkInter(AbstractBoxItem *item);
+  void addNewFullGroup();  
+
+  inline GroupWidget* getCurrentGroup() { return currentGroup; }
+
+  bool isCurrentProject;
+
+public slots:
+
+  GroupScene* searchSceneById(int id);
+  BoxItem* searchBlockItemById(int id);
+  GroupItem* searchGroupItemById(int id);
+  InterfaceItem* searchInterfaceItemById(int id);
+
+  void removeBlock(AbstractBoxItem* item);
+  void duplicateBlock(BoxItem* item);
+  void duplicateInterface(InterfaceItem* item);
+  void addBlock(int idCategory, int idBlock);
+  ConnectionItem *addConnection(InterfaceItem *input, InterfaceItem *output);
+  void removeAllBlockConnections(AbstractBoxItem *block);
+  void removeConnection(ConnectionItem *conn);
+  void removeUselessGroupInterfaces();
+  void showBlocksLibrary();
+  void showProperties(InterfaceItem *inter);
+  void connectInterToGroup(InterfaceItem* item);
+  void disconnectInterFromGroup(InterfaceItem* item);
+  void removeGroupInterface(InterfaceItem* item);
+
+  void addConnection();
+
+  void closeCurrentProject();
+
+private:  
+
+  // the model
+  Parameters* params;
+
+  // attributes that corresponds to the views
+  MainWindow* mainWindow;
+  QList<GroupWidget*> groupList;
+  GroupWidget* currentGroup;
+  GroupWidget *topGroup;
+};
+
+#endif // __DISPATCHER_H__
diff --git a/Exception.cpp b/Exception.cpp
new file mode 100644 (file)
index 0000000..c45c367
--- /dev/null
@@ -0,0 +1,39 @@
+#include "Exception.h"
+
+Exception::Exception(int _id) {
+  id = _id;
+  message = getDefaultMessage();
+}
+
+
+Exception::Exception(const Exception& other) {
+  id = other.id;
+  message = other.message;
+}
+
+QString Exception::getDefaultMessage() {
+  QString ret="";
+  switch(id) {
+  case CONFIGFILE_CORRUPTED : ret = tr("Blast configuration file is corrupted"); break;
+  case CONFIGFILE_NOACCESS : ret = tr("Blast configuration file cannot be read"); break;
+  case PROJECTFILE_CORRUPTED : ret = tr("Project file is corrupted"); break;
+  case PROJECTFILE_NOACCESS : ret = tr("Project file cannot be read"); break;
+  case BLOCKPATH_NOACCESS : ret = tr("Directory containing references cannot be accessed (no rights/existence)"); break;
+  case IMPLPATH_NOACCESS : ret = tr("Directory containing implementations cannot be accessed (no rights/existence)"); break;
+  case BLOCKFILE_CORRUPTED : ret = tr("Block file is corrupted"); break;
+  case BLOCKFILE_NOACCESS : ret = tr("Block file cannot be read"); break;
+  case IMPLFILE_CORRUPTED : ret = tr("Implementation file is corrupted"); break;
+  case IMPLFILE_NOACCESS : ret = tr("Implementation file cannot be read"); break;
+  case BLOCK_NULL : ret = tr("A parameter of type AbstractBlock* has been provided with NULL value."); break;
+  case BLOCK_INVALID_TYPE : ret = tr("A parameter of type AbstractBlock* is used with an incorrect instance type."); break;
+  case IFACE_NULL : ret = tr("A parameter of type AbstractInterface* has been provided with NULL value."); break;
+  case IFACE_INVALID_TYPE : ret = tr("A parameter of type AbstractInterface* is used with an incorrect instance type."); break;
+  case IFACE_MULTIPLICITY_REACHED : ret = tr("Impossible to create another instance of a GraphInterface: the maximum multiplicity is reached."); break;
+  case BLOCKITEM_NULL : ret = tr("A parameter of type AbstractBlockItem* has been provided with NULL value."); break;
+  case BLOCKITEM_INVALID_TYPE : ret = tr("A parameter of type AbstractBlockItem* is used with an incorrect instance type."); break;
+  case WIDTHS_NOT_EQUALS : ret = tr("Two interfaces are connected but don't have the same widths."); break;
+  case INVALID_VALUE : ret = tr("parameter value is not correct (e.g. not numeric, invalid other parameter name, ...)."); break;
+  }
+
+  return ret;
+}
diff --git a/Exception.h b/Exception.h
new file mode 100644 (file)
index 0000000..32b2e49
--- /dev/null
@@ -0,0 +1,80 @@
+/*-==============================================================-
+
+file : Exception.h
+
+creation date : 08/04/2015
+
+author : S. Domas (sdomas@iut-bm.univ-fcomte.fr)
+
+description : 
+
+supp. infos : saved in UTF-8 [éè]
+
+-==============================================================-*/
+#ifndef __EXCEPTION_H__
+#define __EXCEPTION_H__
+
+#include <iostream>
+#include <fstream>
+
+#include <QtCore>
+
+// exceptions for file accesses
+#define CONFIGFILE_NOACCESS 1
+#define CONFIGFILE_CORRUPTED 2
+
+#define PROJECTFILE_NOACCESS 3
+#define PROJECTFILE_CORRUPTED 4
+
+#define BLOCKPATH_NOACCESS 5
+#define IMPLPATH_NOACCESS 6
+
+#define BLOCKFILE_NOACCESS 7
+#define BLOCKFILE_CORRUPTED 8
+
+#define IMPLFILE_NOACCESS 9
+#define IMPLFILE_CORRUPTED 10
+
+#define VHDLFILE_NOACCESS 11
+
+// exceptions for block manipulations
+#define BLOCK_NULL 100
+#define BLOCK_INVALID_TYPE 101
+
+// exceptions for interfaces manipulations
+#define IFACE_NULL 200
+#define IFACE_INVALID_TYPE 201
+#define IFACE_MULTIPLICITY_REACHED 202
+
+// exceptions for block items manipulations
+#define BLOCKITEM_NULL 300
+#define BLOCKITEM_INVALID_TYPE 301
+
+// exceptions for width interfaces validation
+#define WIDTHS_NOT_EQUALS 400
+
+// exceptions for VHDL generation
+#define INVALID_VALUE 500
+
+using namespace std;
+using namespace Qt;
+
+class Exception : public QObject {
+
+public:
+
+  Exception(int _id);
+  Exception(const Exception& other);
+
+  inline int getType() { return id; }
+  inline void setMessage(QString _message) { message = _message; }
+  inline QString getMessage() { return message; }
+  QString getDefaultMessage();
+
+private:  
+  int id;
+  QString message;
+
+};
+
+#endif //__EXCEPTION_H__
diff --git a/FunctionalBlock.cpp b/FunctionalBlock.cpp
new file mode 100644 (file)
index 0000000..f547084
--- /dev/null
@@ -0,0 +1,78 @@
+#include "FunctionalBlock.h"\r
+#include "ReferenceBlock.h"\r
+#include "GroupBlock.h"\r
+#include "AbstractInterface.h"\r
+#include "FunctionalInterface.h"\r
+#include "ReferenceInterface.h"\r
+#include "BlockParameter.h"\r
+\r
+\r
+FunctionalBlock::FunctionalBlock(GroupBlock *_parent, ReferenceBlock *_reference) throw(Exception) :  AbstractBlock() {\r
+  //if (! _reference->isReferenceBlock()) throw(Exception(BLOCK_INVALID_TYPE));\r
+  //if (! _group->isGroupBlock()) throw(Exception(BLOCK_INVALID_TYPE));\r
+  reference = _reference;\r
+  parent = _parent;\r
+  name = reference->getName();\r
+}\r
+\r
+\r
+void FunctionalBlock::parametersValidation(QList<AbstractBlock*>* checkedBlocks, QList<AbstractBlock *> *blocksToConfigure) {\r
+  /*\r
+  checkedBlocks->append(this);\r
+\r
+  foreach(BlockParameter* param, params){\r
+    if(param->isUserParameter() && !param->isValueSet()){\r
+      if(!blocksToConfigure->contains(param->getOwner())){\r
+        blocksToConfigure->append(param->getOwner());\r
+      }\r
+    }\r
+  }\r
+  foreach(AbstractInterface *inter, outputs){\r
+    foreach(AbstractInterface *connectedInter, inter->getConnectedTo()){\r
+      if(!checkedBlocks->contains(connectedInter->getOwner())){\r
+        connectedInter->getOwner()->parametersValidation(checkedBlocks, blocksToConfigure);\r
+      }\r
+    }\r
+  }\r
+  */\r
+}\r
+\r
+bool FunctionalBlock::isFunctionalBlock() {\r
+  return true;\r
+}\r
+\r
+void FunctionalBlock::populate() {\r
+  int i;\r
+  BlockParameter* p;\r
+  AbstractInterface* inter;\r
+\r
+  QList<BlockParameter*> lstParam = reference->getParameters();\r
+  for(i=0;i<lstParam.size();i++) {\r
+    p = lstParam.at(i)->clone();\r
+    addParameter(p);\r
+  }\r
+\r
+  QList<AbstractInterface *> lstInter = reference->getInterfaces();\r
+  for(i=0;i<lstInter.size();i++) {\r
+    try {\r
+      inter = new FunctionalInterface(this, (ReferenceInterface*)lstInter.at(i));\r
+    }\r
+    catch(Exception e) {\r
+      cerr << "Abnormal case: " << qPrintable(e.getDefaultMessage()) << endl << "Aborting execution." << endl;\r
+      exit(1);\r
+    }\r
+\r
+    addInterface(inter);\r
+  }\r
+\r
+}\r
+\r
+\r
+QString FunctionalBlock::getReferenceXmlFile() {\r
+    return ((ReferenceBlock *)reference)->getXmlFile();\r
+}\r
+\r
+QString FunctionalBlock::getReferenceHashMd5()\r
+{\r
+    return ((ReferenceBlock *)reference)->getHashMd5();\r
+}\r
diff --git a/FunctionalBlock.h b/FunctionalBlock.h
new file mode 100644 (file)
index 0000000..1360244
--- /dev/null
@@ -0,0 +1,49 @@
+#ifndef __FUNCTIONALBLOCK_H__\r
+#define __FUNCTIONALBLOCK_H__\r
+\r
+#include <iostream>\r
+\r
+#include <QtCore>\r
+\r
+#include "AbstractBlock.h"\r
+class AbstractBlock;\r
+class ReferenceBlock;\r
+class GroupBlock;\r
+#include "Exception.h"\r
+class Exception;\r
+\r
+\r
+using namespace std;\r
+using namespace Qt;\r
+\r
+/* NOTES :\r
+   - NEVER forget to call populate() after creating an instance of GraphBlock.\r
+ */\r
+\r
+class FunctionalBlock : public AbstractBlock {\r
+public:\r
+\r
+  FunctionalBlock(GroupBlock* _parent, ReferenceBlock* _reference) throw(Exception);\r
+\r
+  // getters\r
+  inline ReferenceBlock* getReference() { return reference; }\r
+\r
+  // setters\r
+\r
+  // testers\r
+  bool isFunctionalBlock();\r
+\r
+  // others\r
+\r
+  void populate(); // create parameters and interface from reference block\r
+  void parametersValidation(QList<AbstractBlock *> *checkedBlocks, QList<AbstractBlock*>* blocksToConfigure);\r
+\r
+  QString getReferenceXmlFile();\r
+  QString getReferenceHashMd5();\r
+\r
+private:  \r
+  ReferenceBlock* reference;\r
+\r
+};\r
+\r
+#endif // __FUNCTIONALBLOCK_H__\r
diff --git a/FunctionalInterface.cpp b/FunctionalInterface.cpp
new file mode 100644 (file)
index 0000000..cc9f765
--- /dev/null
@@ -0,0 +1,197 @@
+#include "ArithmeticEvaluator.h"\r
+#include "FunctionalInterface.h"\r
+#include "ReferenceInterface.h"\r
+#include "GroupInterface.h"\r
+#include "FunctionalBlock.h"\r
+#include "GroupBlock.h"\r
+\r
+\r
+FunctionalInterface::FunctionalInterface(AbstractBlock* _owner, ReferenceInterface *_reference) throw(Exception) : ConnectedInterface(_owner) {\r
+\r
+  if (_owner == NULL) throw(Exception(BLOCK_NULL));\r
+  if (_reference == NULL) throw(Exception(IFACE_NULL));\r
+\r
+  if (! _owner->isFunctionalBlock()) throw(Exception(BLOCK_INVALID_TYPE));\r
+  if (! _reference->isReferenceInterface()) throw(Exception(IFACE_INVALID_TYPE));\r
+\r
+  reference = _reference;\r
+\r
+  name = reference->getName();\r
+  width = reference->getWidth();\r
+  direction = reference->getDirection();\r
+  purpose = reference->getPurpose();\r
+  level = reference->getLevel(); \r
+  connectedFrom = NULL;\r
+}\r
+\r
+bool FunctionalInterface::isFunctionalInterface() {\r
+  return true;\r
+}\r
+\r
+int FunctionalInterface::getInterfaceMultiplicity() {\r
+\r
+  int i=0;\r
+  int ifaceCount = 0;\r
+  FunctionalInterface* iface = NULL;\r
+\r
+  if (direction == AbstractInterface::Input) {\r
+    QList<AbstractInterface *> inputs = owner->getInputs();\r
+    for(i=0;i<inputs.size();i++) {\r
+      iface = AI_TO_FUN(inputs.at(i));\r
+      if (iface->getReference() == reference) {\r
+        ifaceCount += 1;\r
+      }\r
+    }\r
+  }\r
+  else if (direction == AbstractInterface::Output) {\r
+    QList<AbstractInterface *> outputs = owner->getOutputs();\r
+    for(i=0;i<outputs.size();i++) {\r
+      iface = AI_TO_FUN(outputs.at(i));\r
+      if (iface->getReference() == reference) {\r
+        ifaceCount += 1;\r
+      }\r
+    }\r
+  }\r
+  else if (direction == AbstractInterface::InOut) {\r
+    QList<AbstractInterface *> bidirs = owner->getBidirs();\r
+    for(i=0;i<bidirs.size();i++) {\r
+      iface = AI_TO_FUN(bidirs.at(i));\r
+      if (iface->getReference() == reference) {\r
+        ifaceCount += 1;\r
+      }\r
+    }\r
+  }\r
+  if (ifaceCount == 0) {\r
+    return -1;\r
+  }\r
+  else if ( reference->getMultiplicity() == -1) {\r
+    return ifaceCount+1;\r
+  }\r
+  else if ( reference->getMultiplicity() > ifaceCount) {\r
+    return ifaceCount+1;\r
+  }\r
+  return -1;\r
+}\r
+\r
+AbstractInterface *FunctionalInterface::clone() { \r
+  int id = getInterfaceMultiplicity();\r
+  if (id < 0) return NULL;\r
+  FunctionalInterface *inter = new FunctionalInterface(owner, reference);\r
+  inter->setWidth(width);\r
+  inter->setDirection(direction);\r
+  inter->setPurpose(purpose);\r
+  inter->setLevel(level);  \r
+  inter->connectFrom(NULL);\r
+  inter->setName(reference->getName()+"_"+QString::number(id));\r
+  return inter;\r
+}\r
+\r
+bool FunctionalInterface::canConnectTo(AbstractInterface *iface) {\r
+\r
+  /* NOTE :\r
+     necessary conditions :\r
+        - this is an output or in/out interface\r
+        - iface type must be functional or group interface\r
+        - iface->connectedFrom must be NULL\r
+\r
+     valid cases:\r
+     1 - iface is owned by a block (group or func) that is within the same group as the block that own this\r
+        1.1 - this is output and iface is input\r
+        1.2 - both are inout\r
+     2 - iface is owned by the parent group of the block that owns this\r
+        2.1 - this is an output, iface is an output of the group\r
+        2.2 - both are inout\r
+\r
+  */\r
+  if (direction == Input) return false;\r
+  if (iface->isReferenceInterface()) return false;\r
+  if (iface->getConnectedFrom() != NULL) return false;\r
+\r
+  if (getOwner()->getParent() == iface->getOwner()->getParent()) {\r
+\r
+    if ((direction == Output) && (iface->getDirection() == Input)) return true;\r
+    if ((direction == InOut) && (iface->getDirection() == InOut)) return true;\r
+  }\r
+  else if (getOwner()->getParent() == iface->getOwner()) {\r
+    if ((direction == Output) && (iface->getDirection() == Output)) return true;\r
+    if ((direction == InOut) && (iface->getDirection() == InOut)) return true;\r
+  }\r
+\r
+  return false;\r
+\r
+}\r
+\r
+bool FunctionalInterface::canConnectFrom(AbstractInterface *iface) {\r
+\r
+  /* NOTE :\r
+     necessary conditions :\r
+        - this is an input or in/out interface\r
+        - iface type must be functional or group interface\r
+        - this connectedFrom must be NULL\r
+\r
+     valid cases:\r
+     1 - iface is owned by a block (group or func) that is within the same group as the block that own this\r
+        1.1 - this is input and iface is output\r
+        1.2 - both are inout\r
+     2 - iface is owned by the parent group of the block that owns this\r
+        2.1 - this is an input, iface is an input of the group\r
+        2.2 - both are inout\r
+  */\r
+  if (direction == Output) return false;\r
+  if (iface->isReferenceInterface()) return false;\r
+  if (connectedFrom != NULL) return false;\r
+\r
+  if (getOwner()->getParent() == iface->getOwner()->getParent()) {\r
+\r
+    if ((direction == Input) && (iface->getDirection() == Output)) return true;\r
+    if ((direction == InOut) && (iface->getDirection() == InOut)) return true;\r
+  }\r
+  else if (getOwner()->getParent() == iface->getOwner()) {\r
+    if ((direction == Input) && (iface->getDirection() == Input)) return true;\r
+    if ((direction == InOut) && (iface->getDirection() == InOut)) return true;\r
+  }\r
+\r
+  return false;\r
+}\r
+\r
+\r
+void FunctionalInterface::connectionsValidation(QStack<AbstractInterface *> *interfacetoValidate, QList<AbstractInterface *> *validatedInterfaces) throw(Exception) {\r
+\r
+  /*\r
+  //inputs interfaces\r
+  double widthInput, widthOutput;\r
+  if(getDirection() == AbstractInterface::Input){\r
+    widthInput = getDoubleWidth();\r
+    widthOutput = getConnectedFrom()->getDoubleWidth();\r
+    if(widthInput != widthOutput){\r
+      throw new Exception(WIDTHS_NOT_EQUALS);\r
+    }\r
+    foreach(AbstractInterface *inter, getOwner()->getOutputs()){\r
+      if(inter->isConnectedTo()){\r
+        if((!interfacetoValidate->contains(inter)) && (!validatedInterfaces->contains(inter))){\r
+          interfacetoValidate->push(inter);\r
+        }\r
+      }\r
+    }\r
+  }\r
+  //outputs interfaces\r
+  else if(getDirection() == AbstractInterface::Output){\r
+    widthOutput = getDoubleWidth();\r
+    foreach(AbstractInterface *inter, getConnectedTo()){\r
+      widthInput = inter->getDoubleWidth();\r
+      if(widthInput != widthOutput){\r
+        throw new Exception(WIDTHS_NOT_EQUALS);\r
+      }\r
+    }\r
+    foreach(AbstractInterface *inter, getConnectedTo()){\r
+      if((!interfacetoValidate->contains(inter)) && (!validatedInterfaces->contains(inter))){\r
+        interfacetoValidate->push(inter);\r
+      }\r
+    }\r
+  }\r
+  else if(getDirection() == AbstractInterface::InOut){\r
+\r
+  }\r
+\r
+  */\r
+}\r
diff --git a/FunctionalInterface.h b/FunctionalInterface.h
new file mode 100644 (file)
index 0000000..1dfa726
--- /dev/null
@@ -0,0 +1,59 @@
+#ifndef __FUNCTIONALINTERFACE_H__\r
+#define __FUNCTIONALINTERFACE_H__\r
+\r
+#include <iostream>\r
+\r
+#include <QtCore>\r
+#include <QtGui>\r
+\r
+#include "ConnectedInterface.h"\r
+class ReferenceInterface;\r
+\r
+#include "Exception.h"\r
+\r
+using namespace std;\r
+using namespace Qt;\r
+\r
+\r
+/* NOTES :\r
+\r
+  - A FunctionalInterface instance can be obtained by:\r
+     - cloning an existing ReferenceInterface when a new functionalBlock is created by cloning a ReferenceBlock\r
+     - cloning an existing FunctionalInterface when its reference has a multiplicity > 1\r
+\r
+   - For an Input, the list connectedFrom can contain ONLY ONE element\r
+   - For an Output, the list connectedTo can contain several element\r
+   - If connectedTo contains something, then connectedFrom is NULL\r
+   - If connectedFrom contains something, the connectedTo is empty.\r
+ */\r
+\r
+class FunctionalInterface : public ConnectedInterface {\r
+\r
+public :\r
+  FunctionalInterface();\r
+  FunctionalInterface(AbstractBlock* _owner, ReferenceInterface* _reference) throw(Exception); // create a default interface (see AbstractInterface)\r
+\r
+  // getters\r
+  inline ReferenceInterface* getReference() { return reference; }\r
+\r
+  // setters\r
+\r
+  // testers\r
+  bool isFunctionalInterface();\r
+  bool canConnectTo(AbstractInterface* iface);\r
+  bool canConnectFrom(AbstractInterface* iface);\r
+\r
+  // others\r
+\r
+  AbstractInterface* clone();\r
+\r
+  void connectionsValidation(QStack<AbstractInterface*> *interfacetoValidate, QList<AbstractInterface*> *validatedInterfaces) throw(Exception);\r
+  int getInterfaceMultiplicity();\r
+\r
+private:\r
+\r
+  ReferenceInterface* reference;  \r
+\r
+};\r
+\r
+#endif // __FUNCTIONALINTERFACE_H__\r
diff --git a/Graph.cpp b/Graph.cpp
new file mode 100644 (file)
index 0000000..1c87123
--- /dev/null
+++ b/Graph.cpp
@@ -0,0 +1,31 @@
+#include "Graph.h"
+#include "GroupBlock.h"
+#include "ReferenceBlock.h"
+#include "FunctionalBlock.h"
+
+Graph::Graph() {
+  topGroup = new GroupBlock(NULL);
+  topGroup->setName("top group");
+}
+
+Graph::~Graph() {
+  delete topGroup;
+}
+
+QList<AbstractInterface *> Graph::getOutsideInterfaces() {
+  return topGroup->getInterfaces();
+}
+
+GroupBlock* Graph::createChildBlock(GroupBlock* parent) {
+  GroupBlock* b = new GroupBlock(parent);
+  return b;
+}
+
+FunctionalBlock* Graph::addFunctionalBlock(GroupBlock* group, ReferenceBlock* ref) {
+
+  FunctionalBlock* newBlock = new FunctionalBlock(group,ref);
+  newBlock->populate();
+  group->addBlock(newBlock);
+
+  return newBlock;
+}
diff --git a/Graph.h b/Graph.h
new file mode 100644 (file)
index 0000000..7f34682
--- /dev/null
+++ b/Graph.h
@@ -0,0 +1,35 @@
+#ifndef __GRAPH_H__
+#define __GRAPH_H__
+
+#include <iostream>
+
+#include <QtCore>
+#include <QtGui>
+
+class GroupBlock;
+class ReferenceBlock;
+class FunctionalBlock;
+class AbstractInterface;
+
+using namespace std;
+using namespace Qt;
+
+
+class Graph {
+
+public:
+  Graph();
+  ~Graph();
+
+  QList<AbstractInterface *> getOutsideInterfaces();
+  inline GroupBlock* getTopGroup() { return topGroup; }
+
+  GroupBlock* createChildBlock(GroupBlock* parent);
+  FunctionalBlock* addFunctionalBlock(GroupBlock *group, ReferenceBlock *ref);
+
+private:  
+  GroupBlock* topGroup;
+
+};
+
+#endif // __GRAPH_H__
diff --git a/GroupBlock.cpp b/GroupBlock.cpp
new file mode 100644 (file)
index 0000000..4ec7f6b
--- /dev/null
@@ -0,0 +1,78 @@
+#include "GroupBlock.h"
+#include "BlockParameterGeneric.h"
+#include "AbstractInterface.h"
+#include "string.h"
+#include <sstream>
+
+int GroupBlock::counter = 1;
+
+GroupBlock::GroupBlock(GroupBlock *_parent) throw(Exception) :  AbstractBlock() {
+
+  // force topGroup to false if this group has a parent
+  if (_parent != NULL) {    
+    topGroup = false;
+    name = QString("sub_group")+"_"+QString::number(counter++);
+  }
+  else {
+    topGroup = true;
+    name = QString("top_group");
+  }
+  parent = _parent;
+  if (parent != NULL) {
+    // adding this to the child blocks of parent
+    AB_TO_GRP(parent)->addBlock(this);
+  }
+}
+
+GroupBlock::~GroupBlock() {
+  foreach(AbstractBlock* block, blocks) {
+    delete block;
+  }
+}
+
+bool GroupBlock::isGroupBlock() {
+  return true;
+}
+
+void GroupBlock::setParent(AbstractBlock *_parent) {
+  parent = _parent;
+  if (parent != NULL) {
+    topGroup = false;
+  }
+}
+
+void GroupBlock::removeBlock(AbstractBlock* block) {
+    blocks.removeAll(block);
+}
+
+void GroupBlock::parametersValidation(QList<AbstractBlock *> *checkedBlocks, QList<AbstractBlock *> *blocksToConfigure) {
+
+  /*
+  checkedBlocks->append(this);
+
+  foreach(BlockParameter* param, params){
+    if(param->isUserParameter() && !param->isValueSet()){
+      if(!blocksToConfigure->contains(param->getOwner())){
+        blocksToConfigure->append(param->getOwner());
+      }
+    }
+  }
+  foreach(AbstractInterface *inter, outputs){
+    foreach(AbstractInterface *connectedInter, inter->getConnectedTo()){
+      if(!checkedBlocks->contains(connectedInter->getOwner())){
+        connectedInter->getOwner()->parametersValidation(checkedBlocks, blocksToConfigure);
+      }
+    }
+  }
+  */
+}
+
+void GroupBlock::addGenericParameter(QString name, QString type, QString value) {
+  BlockParameter* param = new BlockParameterGeneric(this, name, type, value);
+  params.append(param);
+}
+
+void GroupBlock::removeGenericParameter(QString name) {
+  BlockParameter* p = getParameterFromName(name);
+  if (p != NULL) params.removeAll(p);
+}
diff --git a/GroupBlock.h b/GroupBlock.h
new file mode 100644 (file)
index 0000000..3316637
--- /dev/null
@@ -0,0 +1,47 @@
+#ifndef __GROUPBLOCK_H__
+#define __GROUPBLOCK_H__
+
+#include <iostream>
+
+#include <QtCore>
+
+#include "AbstractBlock.h"
+class AbstractBlock;
+#include "Exception.h"
+class Exception;
+
+using namespace std;
+using namespace Qt;
+
+
+class GroupBlock : public AbstractBlock {
+public:
+
+  GroupBlock(GroupBlock* _parent) throw(Exception);
+  virtual ~GroupBlock();
+
+  // getters
+
+  // setters
+  void setParent(AbstractBlock *_parent);
+
+  // testers
+  bool isGroupBlock();
+  inline bool isTop() { return topGroup; }
+
+  // others
+  inline void addBlock(AbstractBlock* block) { blocks.append(block); }
+  void removeBlock(AbstractBlock* block);
+  void parametersValidation(QList<AbstractBlock *> *checkedBlocks, QList<AbstractBlock*>* blocksToConfigure);  
+  void addGenericParameter(QString name, QString type, QString value);
+  void removeGenericParameter(QString name);
+  // public attributes
+  static int counter;
+
+private:  
+  bool topGroup;  
+  QList<AbstractBlock*> blocks; // contains instances of FunctionalBlock or GroupBlock
+
+};
+
+#endif // __GROUPBLOCK_H__
diff --git a/GroupInterface.cpp b/GroupInterface.cpp
new file mode 100644 (file)
index 0000000..14f8b43
--- /dev/null
@@ -0,0 +1,116 @@
+#include "GroupInterface.h"
+#include "FunctionalInterface.h"
+#include "GroupBlock.h"
+
+GroupInterface::GroupInterface(AbstractBlock* _owner, const QString& _name, int _direction, int _level) throw(Exception) : ConnectedInterface(_owner,_name,"expression","",_direction,AbstractInterface::Data,_level) {
+  if (! _owner->isGroupBlock()) throw(Exception(BLOCK_INVALID_TYPE));
+
+  /* If the owner group is the top group, then all its interfaces are at top level => force them to be top.
+     If not, force them to be basic
+   */
+  if (((GroupBlock*)_owner)->isTop()) {
+    level = AbstractInterface::Top;
+  }
+  else {
+    level = AbstractInterface::Basic;
+  }
+  connectedFrom = NULL;
+}
+
+bool GroupInterface::isGroupInterface() {
+  return true;
+}
+
+AbstractInterface *GroupInterface::clone() {
+    GroupInterface *inter = new GroupInterface(owner,name,direction,level);
+    inter->setWidth(width);
+    inter->setDirection(direction);
+    inter->setPurpose(purpose);
+    inter->setLevel(level);
+    inter->connectFrom(NULL);
+
+    return inter;
+}
+
+
+bool GroupInterface::canConnectTo(AbstractInterface *iface) {
+
+  /* NOTE :
+     necessary conditions :
+        - iface type must be functional or group interface
+        - iface->connectedFrom must be NULL
+
+     valid cases:
+     1 - this is owned by the parent group of the block (group or func) that owns iface
+        1.1 - this is input and iface is input
+        1.2 - both are inout
+     2 - this is owned by a group that has the same parent as the block (group or func) that owns iface
+        2.1 - this is an output, iface is an input of the group
+        2.2 - both are inout
+     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
+
+
+  */
+  if (iface->isReferenceInterface()) return false;
+  if (iface->getConnectedFrom() != NULL) return false;
+
+  if (this->getOwner() == iface->getOwner()->getParent()) {
+    if ((direction == Input) && (iface->getDirection() == Input)) return true;
+    if ((direction == InOut) && (iface->getDirection() == InOut)) return true;
+
+  }
+  else if (this->getOwner()->getParent() == iface->getOwner()->getParent()) {
+    if ((direction == Output) && (iface->getDirection() == Input)) return true;
+    if ((direction == InOut) && (iface->getDirection() == InOut)) return true;
+  }
+  else if (this->getOwner()->getParent() == iface->getOwner()) {
+    if ((direction == Output) && (iface->getDirection() == Output)) return true;
+    if ((direction == InOut) && (iface->getDirection() == InOut)) return true;
+  }
+
+  return false;
+}
+
+bool GroupInterface::canConnectFrom(AbstractInterface *iface) {
+
+  /* NOTE :
+     necessary conditions :
+        - iface type must be functional or group interface
+        - this->connectedFrom must be NULL
+
+     valid cases:
+     1 - this is owned by the parent group of the block (group or func) that owns iface
+        1.1 - this is output and iface is output
+        1.2 - both are inout
+     2 - this is owned by a group that has the same parent as the block (group or func) that owns iface
+        2.1 - this is an input, iface is an output of the group
+        2.2 - both are inout
+     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
+  */
+  if (iface->isReferenceInterface()) return false;
+  if (getConnectedFrom() != NULL) return false;
+
+  if (this->getOwner() == iface->getOwner()->getParent()) {
+    if ((direction == Output) && (iface->getDirection() == Output)) return true;
+    if ((direction == InOut) && (iface->getDirection() == InOut)) return true;
+
+  }
+  else if (this->getOwner()->getParent() == iface->getOwner()->getParent()) {
+    if ((direction == Input) && (iface->getDirection() == Output)) return true;
+    if ((direction == InOut) && (iface->getDirection() == InOut)) return true;
+  }
+  else if (this->getOwner()->getParent() == iface->getOwner()) {
+    if ((direction == Input) && (iface->getDirection() == Input)) return true;
+    if ((direction == InOut) && (iface->getDirection() == InOut)) return true;
+  }
+
+  return false;
+}
+
+void GroupInterface::connectionsValidation(QStack<AbstractInterface*> *interfacetoValidate, QList<AbstractInterface*> *validatedInterfaces) throw(Exception) {
+    cout << "group interface connection validation" << endl;
+}
diff --git a/GroupInterface.h b/GroupInterface.h
new file mode 100644 (file)
index 0000000..2a22dc7
--- /dev/null
@@ -0,0 +1,54 @@
+#ifndef __GROUPINTERFACE_H__
+#define __GROUPINTERFACE_H__
+
+#include <iostream>
+
+#include <QtCore>
+#include <QtGui>
+
+#include "ConnectedInterface.h"
+#include "Exception.h"
+class Exception;
+
+using namespace std;
+using namespace Qt;
+
+/* NOTES :
+
+  - A GroupInterface instance can be obtained by linking it to an interface of an inner block, via a
+     contextual menu that appears when right clicking on the inner interface item.
+    Thus, it is impossible to create a "bypass": an input group interface, directly linked to an output
+    group interface.
+  - the direction (in/out/bi) of this interface is the same as that of the inner interface.
+  - except for the top group, a correct design will always have group interfaces that have
+    both connectedTo and connectedFrom containings something. Indeed, a group interface must be seen
+    as a tunnel to communicate data from outside the group to blocks within the group.
+    Thus, an input group interface has connectedFrom refering to an output interface of a block outside the group
+    and connectedTo listing input interfaces of blocks within the group.
+    An output group interface has connectedFrom refering to an output interface of a bock within the group,
+    and connectedTo listing input interface of blocks outside the group.
+
+ */
+
+
+class GroupInterface : public ConnectedInterface {
+
+public :
+  GroupInterface(AbstractBlock* _owner, const QString& _name, int _direction, int _level = AbstractInterface::Basic) throw (Exception);
+
+  // getters
+
+  // setters
+
+  // testers
+  bool isGroupInterface();
+  bool canConnectTo(AbstractInterface* iface);
+  bool canConnectFrom(AbstractInterface* iface);
+
+  // others
+  AbstractInterface *clone();
+  void connectionsValidation(QStack<AbstractInterface *> *interfacetoValidate, QList<AbstractInterface *> *validatedInterfaces) throw(Exception);
+
+};
+
+#endif // __GROUPINTERFACE_H__
diff --git a/GroupItem.cpp b/GroupItem.cpp
new file mode 100644 (file)
index 0000000..04d7bca
--- /dev/null
@@ -0,0 +1,581 @@
+#include "GroupItem.h"
+
+#include "ConnectionItem.h"
+#include "InterfaceItem.h"
+#include "Dispatcher.h"
+#include "Parameters.h"
+#include "BoxItem.h"
+#include "AbstractBlock.h"
+#include "AbstractInterface.h"
+#include "ConnectedInterface.h"
+#include "GroupScene.h"
+
+
+GroupItem::GroupItem(BoxItem *_parentItem,
+                     AbstractBlock *_refBlock,
+                     Dispatcher *_dispatcher,
+                     Parameters *_params) throw(Exception) :AbstractBoxItem( _refBlock, _dispatcher, _params) {
+
+  parentItem = _parentItem;
+
+  /*
+  minimumBoxWidth = nameWidth+2*nameMargin;
+  minimumBoxHeight = 100;
+  boxHeight = minimumBoxHeight;
+  boxWidth = minimumBoxWidth;
+  */
+  rectTitle = QRectF(0,-(nameHeight+2*nameMargin),nameWidth+2*nameMargin,nameHeight+2*nameMargin);
+  /*
+  totalHeight = boxHeight + rectTitle.height();
+  totalWidth = boxWidth;
+*/
+  selected = false;
+
+
+  setZValue(-100);
+
+  setFlags(QGraphicsItem::ItemIsMovable | QGraphicsItem::ItemIsSelectable | QGraphicsItem::ItemSendsGeometryChanges);  
+
+  updateGeometry();
+  QPointF initPos = QPointF(0.0,0.0) - originPoint;
+  setPos(initPos);
+  cout << "total size of group: " << totalWidth << "," << totalHeight << endl;
+  cout << "pos in scene: " << x() << "," << y() << endl;
+}
+
+GroupItem::~GroupItem() {
+  // since the reference block is nowhere referenced except in this class, it must be deleted here
+  delete refBlock;
+}
+
+bool GroupItem::isGroupItem() {
+  return true;
+}
+
+BoxItem* GroupItem::getParentItem() {
+  return parentItem;
+}
+
+void GroupItem::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget) {
+  if(boxWidth > 0 && boxHeight > 0){
+    if(selected)
+      painter->setPen(Qt::red);
+    else
+      painter->setPen(Qt::black);
+
+    painter->drawRect(0,0,boxWidth,boxHeight);
+    painter->drawRect(rectTitle);
+    painter->drawText(rectTitle,Qt::AlignCenter | Qt::TextWordWrap,refBlock->getName());
+  }
+  foreach(InterfaceItem *item, interfaces){    
+    item->paint(painter);
+  }
+}
+
+/* NOTE:
+   Each time a new block is added in a GroupItem, it is placed
+   at an absolute position of (0,0) within the GroupItem. (NB: the absolute
+   position is computed by item.pos()+item.getOriginPoint()).
+   Thus, there are 3 cases :
+   - a single block is within the GroupItem
+   - several blocks already placed and a new one
+   - several blocks already placed and one is moving.
+
+ */
+void GroupItem::updateMinimumSize() {
+
+  // compute place taken by blocks.
+  int marginConn = 2*(params->arrowWidth+params->arrowLineLength);
+  if (rectTitle.width() > 2*marginConn) {
+    minimumBoxWidth = rectTitle.width();
+  }
+  else {
+    minimumBoxWidth = 2*marginConn;
+  }
+  minimumBoxHeight = 2*marginConn;
+
+  if (getScene() == NULL) return;
+
+  QList<BoxItem *> blocks = getScene()->getBlockItems();
+  if(blocks.length() > 0) {
+    // first, search for blocks that are at (0,0)
+    int xMaxZero = 0;
+    int yMaxZero = 0;
+    int xMax = 0;
+    int yMax = 0;
+    bool isZeroBlocks = false;
+    bool isOtherBlocks = false;
+    foreach(BoxItem* item, blocks) {
+      QPointF p = item->pos() + item->getOriginPoint();
+      if ((p.x()==0.0) && (p.y()==0.0)) {
+        isZeroBlocks = true;
+        if (item->getTotalWidth() > xMaxZero) {
+          xMaxZero = item->getTotalWidth();
+        }
+        if (item->getTotalHeight() > yMaxZero) {
+          yMaxZero = item->getTotalHeight();
+        }
+      }
+      else {
+        isOtherBlocks = true;
+        if(p.x()+item->getTotalWidth() > xMax) {
+          xMax = p.x()+item->getTotalWidth();
+        }
+        if(p.y()+item->getTotalHeight() > yMax) {
+          yMax = p.y()+item->getTotalHeight();
+        }
+      }
+    }
+    if (isZeroBlocks) {
+      if (!isOtherBlocks) {
+        minimumBoxWidth = xMaxZero+2*marginConn;
+        minimumBoxHeight = yMaxZero+2*marginConn;
+      }
+      else {
+        if (xMaxZero+marginConn > xMax) {
+          minimumBoxWidth = xMaxZero+2*marginConn;
+        }
+        else {
+          minimumBoxWidth = xMax+marginConn;
+        }
+        if (yMaxZero+marginConn > yMax) {
+          minimumBoxHeight = yMaxZero+2*marginConn;
+        }
+        else {
+          minimumBoxHeight = yMax+marginConn;
+        }
+      }
+    }
+    else {
+      minimumBoxWidth = xMax+marginConn;
+      minimumBoxHeight = yMax+marginConn;
+    }
+  }
+  //cout << "min group size: " << minimumBoxWidth << "," << minimumBoxHeight << endl;
+}
+
+void GroupItem::updateShape() {
+  updateGeometry();
+}
+
+bool GroupItem::updateGeometry(ChangeType type) {
+
+  QPointF oldOrigin = originPoint;
+  QSize oldSize(totalWidth,totalHeight);
+
+  updateMinimumSize();
+  bool boxSizeChanged = false;
+  if (boxWidth < minimumBoxWidth) {
+    boxWidth = minimumBoxWidth;
+    boxSizeChanged = true;
+  }
+  if (boxHeight < minimumBoxHeight) {
+    boxHeight = minimumBoxHeight;
+     boxSizeChanged = true;
+  }
+  if (boxSizeChanged) {
+    updateInterfacesAndConnections();
+  }
+
+  // compute the max. width of interfaces' name for 4 orientations.  
+  int maxSouth = 0;
+  int maxNorth = 0;
+  int maxEast = 0;
+  int maxWest = 0;
+  int ifaceWidth = 0;
+
+  foreach(InterfaceItem* iface, interfaces) {
+    ifaceWidth = iface->getNameWidth();
+    if (iface->getOrientation() == Parameters::South) {
+      if (ifaceWidth > maxSouth) maxSouth = ifaceWidth+ifaceMargin+params->arrowWidth+params->arrowLineLength;
+    }
+    else if (iface->getOrientation() == Parameters::North) {
+      if (ifaceWidth > maxNorth) maxNorth = ifaceWidth+ifaceMargin+params->arrowWidth+params->arrowLineLength;
+    }
+    else if (iface->getOrientation() == Parameters::East) {
+      if (ifaceWidth > maxEast) maxEast = ifaceWidth+ifaceMargin+params->arrowWidth+params->arrowLineLength;
+    }
+    else if (iface->getOrientation() == Parameters::West) {
+      if (ifaceWidth > maxWest) maxWest = ifaceWidth+ifaceMargin+params->arrowWidth+params->arrowLineLength;
+    }
+  }
+  double x = 0.0;
+  double y = 0.0;
+  totalWidth = boxWidth+maxEast;
+  totalHeight = boxHeight+maxSouth;
+
+  if (maxWest > 0) {
+    x -= maxWest;
+    totalWidth += maxWest;
+  }
+  if (maxNorth > (nameHeight+2*nameMargin)) {
+    y -= maxNorth;
+    totalHeight += maxNorth;
+  }
+  else {
+    y -= nameHeight+2*nameMargin;
+    totalHeight += nameHeight+2*nameMargin;
+  }
+  QSizeF newSize(totalWidth,totalHeight);
+  originPoint.setX(x);
+  originPoint.setY(y);
+
+  if ((boxSizeChanged) || (newSize != oldSize) || (originPoint != oldOrigin)) {
+    //cout << "must change group item shape" << endl;
+    prepareGeometryChange();
+    return true;
+  }
+  return false;
+}
+
+void GroupItem::mouseMoveEvent(QGraphicsSceneMouseEvent *event) {
+
+  if(params->editState == Parameters::EditGroupMove) {
+    QPointF absPos = currentPosition + originPoint;    
+    int gapX = event->scenePos().x() - cursorPosition.x();
+    int gapY = event->scenePos().y() - cursorPosition.y();
+
+    //cout << "block abs. pos: " << absPos.x() << "," << absPos.y() << " | ";
+    //cout << "block current. pos: " << currentPosition.x() << "," << currentPosition.y() << " | ";
+/*
+    if (absPos.x()+gapX < 0) {
+      gapX = -absPos.x();
+    }
+    if (absPos.y()+gapY < 0) {
+      gapY = -absPos.y();
+    }
+    */
+    //cout << "gap: " << gapX << "," << gapY << " | ";
+    //cout << "scene: " << getScene()->sceneRect().x() << "," << getScene()->sceneRect().y() << endl;
+    QPointF gap(gapX,gapY);
+    currentPosition = currentPosition+gap;
+    setPos(currentPosition);
+    cursorPosition = event->scenePos();
+  }
+  else if(params->editState == Parameters::EditGroupResize) {
+
+    int gapX = event->scenePos().x() - cursorPosition.x();
+    int gapY = event->scenePos().y() - cursorPosition.y();
+    //cout << "gap: " << gapX << "," << gapY << endl;
+    switch(currentBorder){
+    case BorderEast: {
+      if(boxWidth+gapX > minimumBoxWidth){
+        boxWidth += gapX;
+      }
+      break;
+    }
+    case BorderSouth: {
+      if(boxHeight+gapY > minimumBoxHeight){
+        boxHeight += gapY;
+      }
+      break;
+    }
+    case CornerSouthEast: {
+      if(boxWidth+gapX > minimumBoxWidth){
+        boxWidth += gapX;
+      }
+      if(boxHeight+gapY > minimumBoxHeight){
+        boxHeight += gapY;
+      }
+      break;
+    }
+    case NoBorder:
+      cout << "abnormal case while resizing block" << endl;
+      break;
+    }
+    updateGeometry();
+    /*
+    // recompute the geometry of the block
+    updateGeometry();
+    // update all interfaces positions
+    foreach(InterfaceItem *item, interfaces){
+      item->updatePosition();
+    }
+    // update all connections from/to this block
+    foreach(ConnectionItem *item, getScene()->getConnectionItems()){
+      if ((item->getFromInterfaceItem()->getOwner() == this) || (item->getToInterfaceItem()->getOwner() == this)) {
+        item->setPathes();
+      }
+    }
+    */
+    cursorPosition = event->scenePos();
+  }
+  else if(params->editState == Parameters::EditInterfaceMove) {
+    prepareGeometryChange();
+    deplaceInterface(event->pos());
+    // recompute the geometry of the block
+    updateGeometry();
+    // update connection from/to the selected interface
+    foreach(ConnectionItem *item, getScene()->getConnectionItems()){
+      if ((item->getFromInterfaceItem() == currentInterface) || (item->getToInterfaceItem() == currentInterface)) {
+        item->setPathes();
+      }
+    }
+    update();
+  }
+}
+
+void GroupItem::mousePressEvent(QGraphicsSceneMouseEvent *event) {
+
+  QPointF pos = event->pos();
+  qreal x = pos.x();
+  qreal y = pos.y();
+
+  QGraphicsItem::mousePressEvent(event);
+
+  if(event->button() == Qt::RightButton) return;
+
+  int mode = getScene()->getEditionMode();
+
+  dispatcher->setCurrentGroupWidget(getScene()->getGroupWindow());
+
+  /* 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)) {
+    InterfaceItem *inter = getInterfaceFromCursor(x,y);
+    if (inter != NULL) {
+
+      if (params->editState == Parameters::EditNoOperation) {
+        getScene()->setSelectedInterface(1,inter);
+        params->setEditState(Parameters::EditStartConnection);
+      }
+      else if (params->editState == Parameters::EditStartConnection) {
+        if (inter == getScene()->getSelectedInterface(1)) {
+          params->setEditState(Parameters::EditAbortConnection);
+        }
+        else {
+          getScene()->setSelectedInterface(2,inter);
+          params->setEditState(Parameters::EditCloseConnection);
+        }
+      }
+    }
+  }
+  */
+  if (mode == GroupScene::ItemEdition) {
+
+    if (params->cursorState == Parameters::CursorOnInterface) {
+      InterfaceItem *inter = getInterfaceFromCursor(x,y);
+      if (inter != NULL) {
+        currentInterface = inter;
+        params->setEditState(Parameters::EditInterfaceMove);
+      }
+    }
+    else if (params->cursorState == Parameters::CursorInGroupTitle) {
+      params->setEditState(Parameters::EditGroupMove);
+      cursorPosition = event->scenePos();
+    }
+    else if (params->cursorState == Parameters::CursorOnBorder) {
+      setFlag(ItemIsMovable, false);
+      cursorPosition = event->scenePos();
+      params->setEditState(Parameters::EditGroupResize);
+    }
+  }
+}
+
+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 (params->editState == Parameters::EditStartConnection) {
+      params->setEditState(Parameters::EditStartConnection);
+      InterfaceItem* iface = getScene()->getSelectedInterface(1);
+      iface->selected = true;
+      update(iface->boundingRect());
+    }
+    else if (params->editState == Parameters::EditAbortConnection) {
+      InterfaceItem* iface = getScene()->getSelectedInterface(1);
+      iface->selected = false;
+      update(iface->boundingRect());
+      getScene()->setSelectedInterface(1,NULL);
+      params->setEditState(Parameters::EditNoOperation);
+    }
+    else if (params->editState == Parameters::EditCloseConnection) {
+      InterfaceItem* iface1 = getScene()->getSelectedInterface(1);
+      InterfaceItem* iface2 = getScene()->getSelectedInterface(2);
+      bool ok = dispatcher->connect(iface1,iface2);
+      if (ok) {
+        iface1->selected = false;
+        update(iface1->boundingRect());
+        getScene()->setSelectedInterface(1,NULL);
+        getScene()->setSelectedInterface(2,NULL);
+        params->setEditState(Parameters::EditNoOperation);
+      }
+    }
+  }
+  */
+  if (mode == GroupScene::ItemEdition) {
+    currentInterface = NULL;
+    setFlag(ItemIsMovable, true);
+    params->editState = Parameters::EditNoOperation;
+  }
+  QGraphicsItem::mouseReleaseEvent(event);
+}
+
+void GroupItem::hoverMoveEvent(QGraphicsSceneHoverEvent *event) {
+  QPointF pos = event->pos();
+  qreal x = pos.x();
+  qreal y = pos.y();
+  currentBorder = NoBorder;
+  int mode = getScene()->getEditionMode();
+
+  if (mode == GroupScene::AddConnection) {
+    InterfaceItem* iface = getInterfaceFromCursor(x,y);
+    if (iface != NULL) {
+      params->cursorState = Parameters::CursorOnInterface;
+      setCursor(Qt::PointingHandCursor);
+    }
+    else {
+      params->cursorState = Parameters::CursorNowhere;
+      setCursor(Qt::ArrowCursor);
+    }
+  }
+  else if (mode == GroupScene::ItemEdition) {
+    int marginE = 5;
+    int marginS = 5;
+
+    InterfaceItem* iface = getInterfaceFromCursor(x,y);
+    if (iface != NULL) {
+      params->cursorState = Parameters::CursorOnInterface;
+      setCursor(Qt::PointingHandCursor);
+    }
+    else if ((x>boxWidth-marginE)&&(x<boxWidth)) {
+
+      params->cursorState = Parameters::CursorOnBorder;
+
+      if ((y>boxHeight-2*marginS)&&(y<boxHeight)) {
+        currentBorder = CornerSouthEast;
+        setCursor(Qt::SizeFDiagCursor);
+      }
+      else {
+        currentBorder = BorderEast;
+        setCursor(Qt::SizeHorCursor);
+      }
+    }
+    else if ((y>boxHeight-marginS)&&(y<boxHeight)) {
+
+      params->cursorState = Parameters::CursorOnBorder;
+
+      if ((x>boxWidth-2*marginE)&&(x<boxWidth)) {
+        currentBorder = CornerSouthEast;
+        setCursor(Qt::SizeFDiagCursor);
+      }
+      else {
+        currentBorder = BorderSouth;
+        setCursor(Qt::SizeVerCursor);
+      }
+    }
+    else {
+      if (rectTitle.contains(x,y)) {
+        params->cursorState = Parameters::CursorInGroupTitle;
+        setCursor(Qt::OpenHandCursor);
+      }
+      else {
+        params->cursorState = Parameters::CursorNowhere;
+        setCursor(Qt::ArrowCursor);
+      }
+    }
+  }
+  QGraphicsItem::hoverMoveEvent(event);
+}
+
+void GroupItem::contextMenuEvent(QGraphicsSceneContextMenuEvent *event) {
+  QMenu menu;
+  QAction* showProperties = NULL;
+  QAction* removeAction = NULL;
+  QAction* renameAction = NULL;
+
+  InterfaceItem* ifaceItem = getInterfaceFromCursor(event->pos().x(), event->pos().y());
+  if( ifaceItem != NULL){
+    showProperties = menu.addAction("Show properties");
+    renameAction = menu.addAction("Rename");
+    menu.addSeparator();
+    /* CAUTION : the interface can be removed only if its
+      connected to only one side, i.e. connectedFrom is null
+      or connectedTo is empty.
+
+    */
+    ConnectedInterface* ref = ifaceItem->refInter;
+    if ((!ref->isConnectedFrom()) || (!ref->isConnectedTo())) {
+      removeAction = menu.addAction("Remove");
+    }
+  }
+  else {
+    renameAction = menu.addAction("Rename");
+  }
+  QAction* selectedAction = menu.exec(event->screenPos());
+
+  if(selectedAction == NULL) return;
+
+  if(selectedAction == renameAction){
+    if(ifaceItem != NULL)
+      dispatcher->rename(ifaceItem);
+    else
+      dispatcher->rename(this);
+  }
+  else if(selectedAction == showProperties){
+    dispatcher->showProperties(ifaceItem);
+  }
+  else if (selectedAction == removeAction) {
+    dispatcher->removeGroupInterface(ifaceItem);
+  }
+}
+
+InterfaceItem* GroupItem::isHoverInterface(QPointF point) {
+  foreach(InterfaceItem *inter, interfaces){
+    if(inter->boundingRect().contains(point))
+      return inter;
+  }
+  return NULL;
+}
+
+void GroupItem::save(QXmlStreamWriter &writer) {
+
+  writer.writeStartElement("group_item");
+
+  QString attrId = QString::number(id);
+  QString attrName(getRefBlock()->getName());
+  QString attrUpperItem = QString::number(-1);
+  if(parentItem != NULL){
+    attrUpperItem = QString::number(parentItem->getId());
+  }
+  QString attrPos = QString::number(pos().x()).append(",").append(QString::number(pos().y()));
+  QString attrDim = QString::number(getWidth()).append(",").append(QString::number(getHeight()));
+
+
+  writer.writeAttribute("id",attrId);
+  writer.writeAttribute("upper_item",attrUpperItem);
+  writer.writeAttribute("name",attrName);
+  writer.writeAttribute("position", attrPos);
+  writer.writeAttribute("dimension", attrDim);
+
+  writer.writeStartElement("group_ifaces");
+
+  writer.writeAttribute("count",QString::number(interfaces.length()));
+
+  foreach(InterfaceItem *item, interfaces){
+    writer.writeStartElement("group_iface");
+
+    writer.writeAttribute("id",QString::number(item->getId()));
+    writer.writeAttribute("name",item->getName());
+    writer.writeAttribute("level",QString(item->refInter->getLevelString()));
+    writer.writeAttribute("direction",QString(item->refInter->getDirectionString()));
+    writer.writeAttribute("orientation",item->getStrOrientation());
+    writer.writeAttribute("position",QString::number(item->getPositionRatio()));
+
+    writer.writeEndElement();
+  }
+
+  writer.writeEndElement();//</interfaces>
+
+  writer.writeEndElement();//</group_item>
+}
diff --git a/GroupItem.h b/GroupItem.h
new file mode 100644 (file)
index 0000000..3882a60
--- /dev/null
@@ -0,0 +1,73 @@
+#ifndef __GROUPITEM_H__
+#define __GROUPITEM_H__
+
+#include <iostream>
+
+#include <QtCore>
+#include <QtGui>
+
+#include "AbstractBoxItem.h"
+class AbstractBoxItem;
+
+class BoxItem;
+class InterfaceItem;
+class Dispatcher;
+class Parameters;
+
+#include "Exception.h"
+
+using namespace std;
+using namespace Qt;
+
+class GroupItem : public AbstractBoxItem {
+
+public:
+  /* CAUTION : the parentItem of a group block IS NOT the group item of the parent scene. It is a BlockItem that is
+     wihtin the parent scene. It is used when interfaceItem are added to the current GroupItem: they must be also added
+     to the parent BlockItem.
+
+     NB : this yields a problem when loading a project because scenes are created before creating group and then block.
+     thus, the parentItem must be initialized afterward when all block items have been created.
+
+   */
+  GroupItem(BoxItem* _parentItem, AbstractBlock *_refBlock, Dispatcher *_dispatcher, Parameters *_params) throw(Exception);
+  ~GroupItem();
+
+  // getters
+  BoxItem* getParentItem();
+
+  // setters
+
+  // testers
+  bool isGroupItem();
+
+  // others  
+  void updateShape();
+  void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget = 0);  
+  void save(QXmlStreamWriter& writer);
+
+protected:
+
+  void updateMinimumSize(); // modify the minimum size
+  bool updateGeometry(ChangeType type);
+
+  void mousePressEvent(QGraphicsSceneMouseEvent *event);
+  void mouseMoveEvent(QGraphicsSceneMouseEvent *event);
+  void mouseReleaseEvent(QGraphicsSceneMouseEvent *event);
+  void hoverMoveEvent(QGraphicsSceneHoverEvent *event);
+  void contextMenuEvent(QGraphicsSceneContextMenuEvent *event);
+
+
+
+private:
+  /* NOTE : parentItem attribute is never NULL except for the top GroupItem
+  in the top scene
+  */
+  BoxItem* parentItem;
+  QRectF rectTitle;  
+
+
+  InterfaceItem *isHoverInterface(QPointF point);
+};
+
+#endif // __GROUPITEM_H__
diff --git a/GroupScene.cpp b/GroupScene.cpp
new file mode 100644 (file)
index 0000000..7ba8c9d
--- /dev/null
@@ -0,0 +1,215 @@
+#include "GroupScene.h"
+
+#include "Dispatcher.h"
+#include "Parameters.h"
+#include "GroupWidget.h"
+#include "GroupItem.h"
+#include "BoxItem.h"
+#include "ConnectionItem.h"
+#include "InterfaceItem.h"
+#include "AbstractBlock.h"
+
+GroupScene::GroupScene(GroupScene *_parentScene, GroupWidget *_window, Dispatcher* _dispatcher, Parameters* _params, bool _topScene, QObject *parent) : QGraphicsScene(parent) {
+  dispatcher = _dispatcher;
+  params = _params;
+  parentScene = _parentScene;
+  if (parentScene != NULL) {
+    parentScene->addChildScene(this);
+  }
+  window = _window;
+  groupItem = NULL;
+  id = -1;
+  topScene = _topScene;
+  editMode = InitState;
+
+  selectedInterfaces[0] = NULL;
+  selectedInterfaces[1] = NULL;
+}
+
+GroupScene::~GroupScene() {
+  blockItems.clear();
+  connectionItems.clear();
+  groupItem = NULL;
+}
+
+void GroupScene::setSelectedInterface(int id, InterfaceItem* iface) {
+  if ((id < 1)|| (id > 2)) return;
+  selectedInterfaces[id-1] = iface;
+}
+
+InterfaceItem* GroupScene::getSelectedInterface(int id) {
+  if ((id < 1)|| (id > 2)) return NULL;
+  return selectedInterfaces[id-1];
+}
+
+QList<BoxItem *> GroupScene::getSelectedBlocks() {
+  QList<BoxItem*> lst;
+  foreach(BoxItem *item, blockItems){
+    if (item->isSelected()){
+      lst.append(item);
+    }
+  }
+  return lst;
+}
+
+int GroupScene::setItemsId(int countInit) {
+  int counter = countInit;
+  groupItem->setId(counter++);
+  foreach(BoxItem *item, blockItems){
+    item->setId(counter++);
+  }
+  return counter;
+}
+
+int GroupScene::setInterfacesId(int countInit) {
+  int counter = countInit;
+  foreach(InterfaceItem* inter, groupItem->getInterfaces()){
+    inter->setId(counter++);
+  }
+  foreach(BoxItem *item, blockItems){
+    foreach(InterfaceItem* inter, item->getInterfaces()){
+      inter->setId(counter++);
+    }
+  }
+  return counter;
+}
+
+QList<AbstractBoxItem*> GroupScene::getGroupAndBlocks() {
+
+  QList<AbstractBoxItem*> lst;
+  lst.append(groupItem);
+  foreach(BoxItem *item, blockItems){
+    lst.append(item);
+  }
+  return lst;
+}
+
+void GroupScene::createBlockItem(AbstractBlock *block) {
+
+  BoxItem* blockItem = new BoxItem(block,dispatcher,params,groupItem);
+  blockItem->setZValue(1);
+  addBlockItem(blockItem);
+}
+
+void GroupScene::addBlockItem(BoxItem* item) {
+  // add item from the viewport
+  //addItem(item);
+  // add item from the QList
+  blockItems.append(item);
+  // repainting the group
+  groupItem->updateShape();
+  // center the new block
+  QPointF newPos((groupItem->getWidth()-item->getTotalWidth())/2.0, (groupItem->getHeight()-item->getTotalHeight())/2.0);
+  newPos = newPos-item->getOriginPoint();
+  item->moveTo(newPos);  
+}
+
+void GroupScene::removeBlockItem(BoxItem* item) {
+  // remove item from the viewport
+  removeItem(item);
+  // remove item from the QList
+  blockItems.removeAll(item);
+  // repainting the group
+  groupItem->updateShape();
+}
+
+void GroupScene::createConnectionItem(InterfaceItem *iface1, InterfaceItem *iface2) {
+  ConnectionItem* conn = new ConnectionItem(iface1,iface2, dispatcher, params, groupItem);
+  addConnectionItem(conn);
+}
+
+ConnectionItem* GroupScene::searchConnectionItem(InterfaceItem *iface1, InterfaceItem *iface2) {
+  foreach(ConnectionItem* conn , connectionItems) {
+    if ( ((conn->getFromInterfaceItem() == iface1) && (conn->getToInterfaceItem() == iface2)) ||
+         ((conn->getFromInterfaceItem() == iface2) && (conn->getToInterfaceItem() == iface1))) {
+      return conn;
+    }
+  }
+}
+
+void GroupScene::addConnectionItem(ConnectionItem* item) {
+  // add item from the viewport
+  //addItem(item);
+  // add item from the QList
+  connectionItems.append(item);
+}
+
+void GroupScene::removeConnectionItem(ConnectionItem* item) {
+  // remove item from the viewport
+  removeItem(item);
+  // remove item from the QList
+  connectionItems.removeAll(item);
+}
+
+void GroupScene::setGroupItem(GroupItem *group) {
+  if ((groupItem == NULL) && (group != NULL)) {
+    groupItem = group;
+    addItem(group);
+  }
+}
+
+void GroupScene::removeGroupItem() {
+  // remove item from the viewport
+  removeItem(groupItem);
+  groupItem = NULL;
+}
+
+QList<ConnectionItem *> GroupScene::getInterfaceConnections(InterfaceItem *item) {
+  QList<ConnectionItem*> list;
+  foreach(ConnectionItem *conn, connectionItems){
+    if(conn->getFromInterfaceItem() == item || conn->getToInterfaceItem() == item){
+      list.append(conn);
+    }
+  }
+  return list;
+}
+
+void GroupScene::unselecteInterfaces() {
+
+  if (selectedInterfaces[0] != NULL) {
+    selectedInterfaces[0]->selected = false;
+    selectedInterfaces[0] == NULL;
+  }
+  if (selectedInterfaces[1] != NULL) {
+    selectedInterfaces[1]->selected = false;
+    selectedInterfaces[1] == NULL;
+  }
+}
+
+void GroupScene::updateConnectionItemsShape() {
+
+  foreach(ConnectionItem* conn, connectionItems){
+    conn->setPathes();
+  }
+}
+
+void GroupScene::save(QXmlStreamWriter &writer) {
+  writer.writeStartElement("scene");
+  writer.writeAttribute("id",QString::number(id));
+  groupItem->save(writer);
+
+  writer.writeStartElement("block_items");
+
+  QList<BoxItem *> functionalBlocks;
+  QList<BoxItem *> groupBlocks;
+
+  foreach(BoxItem *item, blockItems){
+    if(item->getRefBlock()->isFunctionalBlock()){
+      functionalBlocks.append(item);
+    } else if(item->getRefBlock()->isGroupBlock()){
+      groupBlocks.append(item);
+    }
+  }
+  writer.writeAttribute("functional_count",QString::number(functionalBlocks.length()));
+  writer.writeAttribute("group_count",QString::number(groupBlocks.length()));
+
+  foreach(BoxItem* item, functionalBlocks) {
+    item->save(writer);
+  }
+  foreach(BoxItem* item, groupBlocks) {
+    item->save(writer);
+  }
+  writer.writeEndElement(); // block_items
+  writer.writeEndElement(); // scene
+}
+
diff --git a/GroupScene.h b/GroupScene.h
new file mode 100644 (file)
index 0000000..8561482
--- /dev/null
@@ -0,0 +1,110 @@
+#ifndef __GROUPSCENE_H__
+#define __GROUPSCENE_H__
+
+#include <QtCore>
+#include <QtGui>
+#include <QtWidgets>
+
+class Dispatcher;
+class Parameters;
+class AbstractBlock;
+class GroupWidget;
+class GroupItem;
+class BoxItem;
+class AbstractBoxItem;
+class ConnectionItem;
+class InterfaceItem;
+
+using namespace std;
+using namespace Qt;
+
+/* NOTES :
+
+ - A GroupScene is composed of a single GroupItem that contains BlockItem and ConnectionItem
+   The GroupItem is stored in the mainGroup attribute
+
+ - A GroupScene is instanciated whenever there is a GroupItem that must be created, i.e.
+  for the top scene or for subgroups.
+
+  - This class is a subclass of QGraphicsScene by convenience but it's goal is more to list
+  the different inner items. Thus, all operations that add/remove items to the scene will also
+  add them in the QList
+ */
+
+class GroupScene : public QGraphicsScene {
+
+public:
+
+  /* edition mode of the window:
+     - AddBlock: can only add blocks to the scene
+     - AddConnection: can only add connections to the scene
+     - AddGroup: while a new group (empty or from selected blocks) is created
+     - ItemEdtion: can move/resize blocks/interfaces, remove blocks/interface/group, ...
+   */
+  enum EditMode { InitState, AddBlock, AddConnection, AddGroup, ItemEdition };
+
+  GroupScene(GroupScene* _parentScene, GroupWidget* _window, Dispatcher* _dispatcher, Parameters* _params, bool topScene = false, QObject *parent = 0);
+  ~GroupScene();
+
+  // attributes getters
+  inline GroupItem* getGroupItem() {return groupItem;}
+  inline QList<BoxItem*> getBlockItems() { return blockItems; }
+  inline QList<ConnectionItem*> getConnectionItems() { return connectionItems; }
+  inline QList<GroupScene*> getChildrenScene() { return childrenScene; }
+  inline GroupWidget* getGroupWindow() { return window; }
+  inline int getId() { return id; }
+  inline EditMode getEditionMode() { return editMode; }
+  InterfaceItem* getSelectedInterface(int id);
+
+  // attributes setters
+  inline void setWindow(GroupWidget* _window) { window = _window; }
+  void setGroupItem(GroupItem* group);
+  inline void setId(int id) { this->id = id; }
+  inline void setEditionMode(EditMode mode) { editMode = mode; }
+  void setSelectedInterface(int id, InterfaceItem* iface);
+
+  // attributes testers
+  inline bool isTopScene() { return topScene; }
+
+
+  // others  
+  void createBlockItem(AbstractBlock* block);
+  void addBlockItem(BoxItem* item);
+  void removeBlockItem(BoxItem* item);
+  void createConnectionItem(InterfaceItem* iface1, InterfaceItem* iface2);
+  ConnectionItem* searchConnectionItem(InterfaceItem* iface1, InterfaceItem* iface2);
+  void addConnectionItem(ConnectionItem* item);
+  void removeConnectionItem(ConnectionItem* item);
+  void removeGroupItem();
+  inline void addChildScene(GroupScene* child) { childrenScene.append(child); }
+  void unselecteInterfaces();
+
+  QList<AbstractBoxItem*> getGroupAndBlocks();
+  QList<BoxItem *> getSelectedBlocks();
+
+  QList<ConnectionItem *> getInterfaceConnections(InterfaceItem *item);
+
+  int setItemsId(int countInit=1);
+  int setInterfacesId(int countInit=1);
+
+  void updateConnectionItemsShape();
+
+  void save(QXmlStreamWriter& writer);
+
+private:
+  Dispatcher *dispatcher;
+  Parameters *params;
+  GroupScene* parentScene; // the parnet scene, =NULL for top scene
+  GroupWidget* window; // the GroupWindow that contains that scene
+  int id;
+  GroupItem *groupItem; // mandatory to be an instance of GroupItem.
+  QList<ConnectionItem*> connectionItems;
+  QList<BoxItem*> blockItems;
+  QList<GroupScene*> childrenScene;
+  bool topScene;
+  EditMode editMode;
+  InterfaceItem* selectedInterfaces[2]; // selected iface 1 in AddConnection mode
+
+};
+
+#endif // __GROUPSCENE_H__
diff --git a/GroupWidget.cpp b/GroupWidget.cpp
new file mode 100644 (file)
index 0000000..1446a13
--- /dev/null
@@ -0,0 +1,279 @@
+#include "GroupWidget.h"
+
+#include "Dispatcher.h"
+#include "Parameters.h"
+
+#include "GroupScene.h"
+#include "GroupBlock.h"
+#include "BoxItem.h"
+#include "GroupItem.h"
+#include "ConnectionItem.h"
+#include "Graph.h"
+
+GroupWidget::GroupWidget(GroupWidget *_upperGroup, Dispatcher *_dispatcher,
+                         Parameters *_params,
+                         QWidget *parent) : QWidget(parent) {
+  upperGroup = _upperGroup;
+  dispatcher = _dispatcher;
+  params = _params;
+  if (upperGroup == NULL) {
+    topGroup = true;
+    scene = new GroupScene(NULL, this, dispatcher, params, true);
+  }
+  else {
+    topGroup = true;
+    scene = new GroupScene(upperGroup->getScene(), this, dispatcher, params, false);
+  }
+
+  layout = new QGridLayout;
+
+  QGraphicsView *view = new QGraphicsView(scene);
+  layout->addWidget(view,1,0,1,3);
+
+  createActions();
+  createToolbar();
+  setLayout(layout);
+  setFocusPolicy(Qt::StrongFocus);
+  setFocus();
+
+  scene->setEditionMode(GroupScene::ItemEdition);
+  updateBlockButton();
+
+}
+
+GroupWidget::~GroupWidget(){}
+
+void GroupWidget::changeConnectionMode(int mode) {
+  /*
+  QPalette pal = buttonNewConnection->palette();
+
+  if(mode == -1){
+
+    if(params->sceneMode != Parameters::EditOnConnection){
+      params->sceneMode = Parameters::EditOnConnection;
+      pal.setColor(QPalette::Button, QColor(Qt::lightGray));
+
+    } else {
+      params->sceneMode = Parameters::EditNoOperation;
+      pal.setColor(QPalette::Button, QColor("#edeceb"));
+      dispatcher->unselectAllInterfaces();
+    }
+  } else if(mode == Parameters::EditOnConnection){
+    params->sceneMode = Parameters::EditOnConnection;
+    pal.setColor(QPalette::Button, QColor(Qt::lightGray));
+  } else {
+    params->sceneMode = Parameters::EditNoOperation;
+    pal.setColor(QPalette::Button, QColor("#edeceb"));
+  }
+  dispatcher->unselectAllInterfaces();
+  buttonNewConnection->setAutoFillBackground(true);
+  buttonNewConnection->setPalette(pal);
+  buttonNewConnection->update();
+  */
+}
+
+
+void GroupWidget::enableGroupButton(bool b) {
+  newGroupAct->setEnabled(b);
+}
+
+
+void GroupWidget::mousePressEvent(QMouseEvent *e) {
+  dispatcher->setCurrentGroupWidget(this);
+  QWidget::mousePressEvent(e);
+}
+
+void GroupWidget::focusInEvent(QFocusEvent *e) {
+  /*
+  if(params->currentWindow != this){
+    params->setCurrentWindow(this);
+    changeConnectionMode(false);
+  }
+  */
+}
+
+void GroupWidget::closeEvent(QCloseEvent *e) {
+  clearFocus();
+  focusNextChild();
+}
+
+
+void GroupWidget::createActions() {  
+
+  butAddConnection = new QToolButton(this);
+  butAddConnection->setIcon(QPixmap::fromImage(QImage("icons/add_connection.png")));
+  butAddConnection->setToolTip("Adding connections");
+  QPalette pal = butAddConnection->palette();
+  butBaseColor = pal.color(QPalette::Button);
+  connect(butAddConnection, SIGNAL(clicked()), this, SLOT(slotAddConnection()));
+
+  butEdit = new QToolButton(this);
+  butEdit->setIcon(QPixmap::fromImage(QImage("icons/edit_block.png")));
+  butEdit->setToolTip("Edit items");
+  connect(butEdit, SIGNAL(clicked()), this, SLOT(slotEdit()));
+
+  copyBlockAct = new QAction(tr("&Copy block"), this);
+  copyBlockAct->setIcon(QPixmap::fromImage(QImage("icons/copy.png")));
+  copyBlockAct->setStatusTip(tr("Copy the selected block"));
+  connect(copyBlockAct, SIGNAL(triggered()), this, SLOT(slotCopyBlock()));  
+
+  newEmptyGroupAct = new QAction(tr("&Create a new empty group"), this);
+  newEmptyGroupAct->setIcon(QPixmap::fromImage(QImage("icons/add_group_void.png")));
+  newEmptyGroupAct->setStatusTip(tr("Create a new empty group"));
+  connect(newEmptyGroupAct, SIGNAL(triggered()), this, SLOT(slotNewEmptyGroup()));
+
+  newGroupAct = new QAction(tr("&Create a new group"), this);
+  newGroupAct->setIcon(QPixmap::fromImage(QImage("icons/add_group_select.png")));
+  newGroupAct->setStatusTip(tr("Create a new group"));
+  newGroupAct->setDisabled(true);
+  connect(newGroupAct, SIGNAL(triggered()), this, SLOT(slotNewGroup()));
+
+  deleteAct = new QAction(tr("&Delete selected elements"), this);
+  deleteAct->setIcon(QPixmap::fromImage(QImage("icons/delete.png")));
+  deleteAct->setStatusTip(tr("Delete selected elements"));
+  connect(deleteAct, SIGNAL(triggered()), this, SLOT(slotDeleteItems()));
+
+  selectAllAct = new QAction(tr("&Select all elements"), this);
+  selectAllAct->setIcon(QPixmap::fromImage(QImage("icons/delete.png")));
+  selectAllAct->setStatusTip(tr("Select all elements"));
+  connect(selectAllAct, SIGNAL(triggered()), this, SLOT(slotSelectAll()));
+
+  unselectAllAct = new QAction(tr("&unselect all elements"), this);
+  unselectAllAct->setIcon(QPixmap::fromImage(QImage("icons/delete.png")));
+  unselectAllAct->setStatusTip(tr("Unselect all elements"));
+  connect(unselectAllAct, SIGNAL(triggered()), this, SLOT(slotUnselectAll()));
+}
+
+void GroupWidget::createToolbar() {
+  toolbarEditMode = new QToolBar(tr("Mode"));
+  toolbarAdd = new QToolBar(tr("Group"));
+  toolbarTools = new QToolBar(tr("Tools"));
+
+  toolbarEditMode->addWidget(new QLabel("Mode"));
+  toolbarTools->addWidget(new QLabel("Tools"));
+
+  toolbarEditMode->addSeparator();
+  toolbarTools->addSeparator();
+
+  toolbarEditMode->addWidget(butAddConnection);
+  toolbarEditMode->addWidget(butEdit);
+
+  toolbarAdd->addAction(copyBlockAct);
+  toolbarAdd->addAction(newEmptyGroupAct);
+  toolbarAdd->addAction(newGroupAct);
+
+  toolbarTools->addAction(deleteAct);
+  toolbarTools->addAction(selectAllAct);
+  toolbarTools->addAction(unselectAllAct);
+
+  layout->addWidget(toolbarEditMode,0,0);
+  layout->addWidget(toolbarAdd,0,1);
+  layout->addWidget(toolbarTools,0,2);
+}
+
+void GroupWidget::slotEdit() {
+  dispatcher->unselectAllItems();
+  getScene()->setEditionMode(GroupScene::ItemEdition);
+  updateBlockButton();
+}
+
+void GroupWidget::slotCopyBlock() {
+  foreach (BoxItem *item, params->getCurrentScene()->getBlockItems()) {
+    if(item->isSelected()){
+      dispatcher->duplicateBlock(item);
+    }
+  }
+}
+
+void GroupWidget::slotAddConnection() {
+  dispatcher->unselectAllItems();
+  getScene()->setEditionMode(GroupScene::AddConnection);
+  updateBlockButton();
+}
+
+void GroupWidget::updateBlockButton() {
+
+  // reset all buttons to light gray
+  QPalette pal = butAddConnection->palette();
+  pal.setColor(QPalette::Button, butBaseColor);
+
+  butAddConnection->setAutoFillBackground(true);
+  butAddConnection->setPalette(pal);
+  butAddConnection->update();
+  butEdit->setAutoFillBackground(true);
+  butEdit->setPalette(pal);
+  butEdit->update();  
+
+  // set the good one to dark gray
+  pal.setColor(QPalette::Button, QColor(Qt::darkGray));
+
+  if(getScene()->getEditionMode() == GroupScene::AddConnection) {
+    butAddConnection->setAutoFillBackground(true);
+    butAddConnection->setPalette(pal);
+    butAddConnection->update();
+  }
+  else if(getScene()->getEditionMode() == GroupScene::ItemEdition) {
+    butEdit->setAutoFillBackground(true);
+    butEdit->setPalette(pal);
+    butEdit->update();
+  }
+
+}
+
+void GroupWidget::slotNewEmptyGroup() {
+
+  // creating the GroupBlock in graph model
+  GroupBlock* groupBlock = params->addGroupBlock();
+  // creating the BlockItem in the inner scene
+  BoxItem* block = new BoxItem(groupBlock, dispatcher, params, scene->getGroupItem());
+
+  GroupWidget* child = dispatcher->createChildScene(this,block);
+  child->show();
+}
+
+void GroupWidget::slotNewGroup()
+{
+  dispatcher->addNewFullGroup();
+}
+
+void GroupWidget::slotDeleteItems() {
+  foreach (BoxItem *item, scene->getBlockItems()) {
+    if(item->isSelected()){
+      dispatcher->removeBlock(item);
+    }
+  }
+  foreach (ConnectionItem *item, scene->getConnectionItems()) {
+    if(item->isSelected()){
+      dispatcher->removeConnection(item);
+    }
+  }
+}
+
+void GroupWidget::slotSelectAll()
+{
+  foreach(QGraphicsItem *item, params->getCurrentScene()->items()){
+    if(item->data(0) == "block"){
+      BoxItem *b = dynamic_cast<BoxItem*>(item);
+      b->setSelected(true);
+    } else if(item->data(0) == "connection"){
+      ConnectionItem *c = dynamic_cast<ConnectionItem*>(item);
+      c->setSelected(true);
+    }
+    item->update(item->boundingRect());
+  }
+}
+
+void GroupWidget::slotUnselectAll()
+{
+  foreach(QGraphicsItem *item, params->getCurrentScene()->items()){
+    if(item->data(0) == "block"){
+      BoxItem *b = dynamic_cast<BoxItem*>(item);
+      b->setSelected(false);
+    } else if(item->data(0) == "connection"){
+      ConnectionItem *c = dynamic_cast<ConnectionItem*>(item);
+      c->setSelected(false);
+    }
+
+    item->update(item->boundingRect());
+  }
+}
diff --git a/GroupWidget.h b/GroupWidget.h
new file mode 100644 (file)
index 0000000..bfdb78b
--- /dev/null
@@ -0,0 +1,85 @@
+#ifndef __GROUPWIDGET_H__
+#define __GROUPWIDGET_H__
+
+#include <QtWidgets>
+
+class Dispatcher;
+class Parameters;
+class GroupScene;
+
+
+
+class GroupWidget : public QWidget {
+  Q_OBJECT
+public:
+
+  explicit GroupWidget(GroupWidget* _upperGroup, Dispatcher* _dispatcher, Parameters* _params, QWidget *parent = 0);
+
+  // getters
+  inline GroupScene *getScene() {return scene;}
+  inline QToolButton* getButtonNewConnection(){return butAddConnection;}
+
+  // testers
+  inline bool isTopGroup() { return topGroup;}
+
+  // others
+  void changeConnectionMode(int mode = -1);
+
+
+  ~GroupWidget();
+
+  void enableGroupButton(bool b);
+
+protected:
+  void mousePressEvent(QMouseEvent *e);
+  void focusInEvent(QFocusEvent *e);
+  void closeEvent(QCloseEvent *e);
+
+private:
+  GroupWidget* upperGroup; // NB:for convenience. NULL if it contains the top scene
+  bool topGroup;
+
+  GroupScene *scene;
+  Dispatcher *dispatcher;
+  Parameters *params;
+
+  void createActions();
+  void createToolbar();
+
+  QToolButton* butAddConnection;
+  QToolButton* butEdit;
+  void updateBlockButton();
+  QColor butBaseColor;
+
+  QAction *copyBlockAct;    
+
+  QAction *newEmptyGroupAct;
+  QAction *newGroupAct;
+
+  QAction *deleteAct;
+  QAction *selectAllAct;
+  QAction *unselectAllAct;
+
+  QToolBar *toolbarEditMode;
+  QToolBar *toolbarAdd;
+  QToolBar *toolbarTools;
+
+
+  QGridLayout *layout;
+
+signals:
+
+private slots:  
+  void slotCopyBlock();
+  void slotAddConnection();
+  void slotEdit();
+
+  void slotNewEmptyGroup();
+  void slotNewGroup();
+
+  void slotDeleteItems();
+  void slotSelectAll();
+  void slotUnselectAll();
+};
+
+#endif // __GROUPWIDGET_H__
diff --git a/InterfaceItem.cpp b/InterfaceItem.cpp
new file mode 100644 (file)
index 0000000..552e159
--- /dev/null
@@ -0,0 +1,445 @@
+#include "InterfaceItem.h"
+
+#include "Parameters.h"
+#include "GroupInterface.h"
+#include "FunctionalInterface.h"
+#include "BoxItem.h"
+
+int InterfaceItem::counter = 0;
+
+InterfaceItem::InterfaceItem(double _position,
+                             int _orientation,
+                             ConnectedInterface *_refInter,
+                             AbstractBoxItem* _owner,
+                             Parameters* _params){
+  positionRatio = _position;
+  orientation = _orientation;
+  refInter = _refInter;
+
+  // CAUTION : the owner must add explicitely this item to its interface, calling addInterface()
+  owner = _owner;
+  params = _params;
+  selected = false;
+  name = refInter->getName();
+  QFontMetrics fmName(params->defaultIfaceFont);
+  nameWidth = fmName.width(name);
+  nameHeight = fmName.height();
+  // by default, only data interface are visible
+  if (refInter->getPurpose() == AbstractInterface::Data) {
+    visible = true;
+  }
+  else {
+    visible = false;
+  }
+
+  this->id = InterfaceItem::counter++;
+
+  updatePosition();
+}
+
+
+InterfaceItem::InterfaceItem(){
+  this->id = counter++;
+}
+
+/* boundingRect() : give the bounding rect in the blockitem coord. system */
+QRectF InterfaceItem::boundingRect() const {
+
+  QPointF pointHG;
+  QSizeF s;
+
+  switch(orientation){
+  case Parameters::East :
+    pointHG = QPointF(originPoint.x(),originPoint.y()-(params->arrowHeight/2.0));
+    s = QSizeF(params->arrowWidth+params->arrowLineLength, params->arrowHeight);
+    break;
+  case Parameters::North :
+    pointHG = QPointF(originPoint.x()-(params->arrowHeight/2.0),originPoint.y()-params->arrowWidth-params->arrowLineLength);
+    s = QSizeF(params->arrowHeight,params->arrowWidth+params->arrowLineLength);
+    break;
+  case Parameters::West :
+    pointHG = QPointF(originPoint.x()-params->arrowLineLength-params->arrowWidth,originPoint.y()-(params->arrowHeight/2.0));
+    s = QSizeF(params->arrowWidth+params->arrowLineLength, params->arrowHeight);
+    break;
+  case Parameters::South :
+    pointHG = QPointF(originPoint.x()-(params->arrowHeight/2.0),originPoint.y());
+    s = QSizeF(params->arrowHeight, params->arrowWidth+params->arrowLineLength);
+    break;
+  default :
+    pointHG = QPointF();
+    s = QSizeF();
+    break;
+  }  
+
+  return QRectF(pointHG,s);
+}
+
+void InterfaceItem::paint(QPainter *painter) {
+
+  if(visible) {
+
+    painter->save();
+
+    if(selected) {
+      painter->setPen(QPen(Qt::red,2));
+    }
+    else if(refInter->getLevel() == AbstractInterface::Basic) {
+      painter->setPen(QPen(Qt::darkCyan,1));
+    }
+    else if(refInter->getLevel() == AbstractInterface::Top) {
+      painter->setPen(QPen(Qt::black,1));
+    }
+
+    painter->translate(originPoint);
+
+    switch(orientation) {
+    case Parameters::North:
+      painter->rotate(-90);
+      break;
+    case Parameters::West:
+      painter->rotate(180);
+      break;
+    case Parameters::South:
+      painter->rotate(90);
+      break;
+    }
+
+    // draw arrows
+    if(refInter->getDirection() == AbstractInterface::Input) {
+      painter->drawPath(params->inArrow);
+    }
+    else if(refInter->getDirection() == AbstractInterface::Output) {
+      painter->drawPath(params->outArrow);
+    } else if(refInter->getDirection() == AbstractInterface::InOut) {
+      painter->drawPath(params->inArrow);
+      painter->drawPath(params->outArrow);
+    }
+
+    // draw names
+
+    // reset to normal if at west
+    if(orientation == Parameters::West){
+      painter->rotate(180);
+    }
+
+    painter->setFont(params->defaultIfaceFont);
+
+    QFontMetrics fm = painter->fontMetrics();
+    int w = nameWidth + owner->getIfaceMargin();
+    int h = nameHeight;
+
+    if(orientation == Parameters::West){
+
+      if(owner->isGroupItem()){
+        painter->drawText(-(w+params->arrowWidth+params->arrowLineLength),-h/2,w,h,Qt::AlignLeft | Qt::TextWordWrap, refInter->getName());
+      }
+      else if(owner->isBoxItem()){
+        painter->drawText(0,-h/2,w,h,Qt::AlignRight | Qt::TextWordWrap, refInter->getName());
+      }
+    }
+    else  {
+
+      if(owner->isGroupItem()) {
+        painter->drawText(params->arrowWidth+params->arrowLineLength,-h/2,w,h,Qt::AlignRight | Qt::TextWordWrap, refInter->getName());
+      }
+      else if(owner->isBoxItem()) {
+        painter->drawText(-w,-h/2,w,h,Qt::AlignLeft | Qt::TextWordWrap, refInter->getName());
+      }
+    }    
+
+    painter->restore();
+  }
+}
+
+QPointF InterfaceItem::getEndPointInGroup() {
+  QPointF 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);
+  }
+
+  //cout << "iface end point in group item: " << p.x() << "," << p.y() << endl;
+  return p;
+}
+
+void InterfaceItem::setOriginPoint() {
+  switch(orientation){
+  case Parameters::East:
+    originPoint = QPointF(owner->getWidth(),position);
+    break;
+  case Parameters::North:
+    originPoint = QPointF(position,0);
+    break;
+  case Parameters::West:
+    originPoint = QPointF(0,position);
+    break;
+  case Parameters::South:
+    originPoint = QPointF(position,owner->getHeight());
+    break;
+  }
+}
+
+QString InterfaceItem::getStrOrientation() {
+  QString str = NULL;
+  switch(orientation){
+  case Parameters::North :
+    str = QString("north");
+    break;
+  case Parameters::South :
+    str = QString("south");
+    break;
+  case Parameters::East :
+    str = QString("east");
+    break;
+  case Parameters::West :
+    str = QString("west");
+    break;
+  }
+
+  return str;
+}
+
+int InterfaceItem::getIntOrientation(QString str) {
+  if(str == "west") return Parameters::West;
+  if(str == "east") return Parameters::East;
+  if(str == "south") return Parameters::South;
+  if(str == "north") return Parameters::North;
+  return -1;
+}
+
+
+/* connectWith() :
+  - modify all necessary attributes in the model to create a connection
+  between current InterfaceItem and iface. Note that the source and destination
+  are deduced from the direction (In, Out) and the type of the owner (funcitonal, group)
+
+  CAUTION: No security checks are done. This method must be called only if canConnectWith has been called and returned true.
+
+  NOTE : conditions so that this InterfaceItem can be connected with inter.
+     (i.e. current one can connect to inter OR inter can connect to current)
+
+     Here are all the possible combinations, depending on the type of the
+     block/item and direction of the interface, which are :
+     GI/GB : a GroupItem referencing a GroupBlock (single solution for GI)
+     BI/FB : a BlockItem referencing a FunctionalBlock
+     BI/GB : a BlockItem referencing a GroupBlock
+
+     For GI/GB:
+     - Input can connect with BI/FB or BI/GB Input
+     - Output can connect with BI/FB or BI/GB Output
+
+     For BI/FB:
+     - Input can connect with:
+         GI/GB Input
+         BI/FB Output
+         BI/GB Output
+     - Output can connect with:
+         GI/GB Output
+         BI/FB Input
+         BI/GB Input
+
+     For BI/GB:
+     - Input can connect with:
+         GI/GB Input
+         BI/FB Output
+         BI/GB Output
+     - Output can connect with:
+         GI/GB Output
+         BI/FB Input
+         BI/GB Input
+
+    And whatever the case an InOut can only connect with an InOut
+    We note that:
+       - the IG does not allow the connect a GI/GB interface to an
+       interface of another GI/GB, thus the case is not considered above.
+       - BI/FB and BI/GB are the same.
+       - the cases where direction are the same only occur when
+       the 2 items are of different type (GI and BI)
+       - the cases where directions are different only occur when
+       the 2 are of both BlockItem
+
+*/
+bool InterfaceItem::connectWith(InterfaceItem *iface) {
+  ConnectedInterface* interThis = refInter; // the reference of this
+  ConnectedInterface* interOther = iface->refInter; // the reference of the other
+  ConnectedInterface* src = NULL, *dest = NULL;
+
+  if(interThis->getDirection() == AbstractInterface::InOut && interOther->getDirection() == AbstractInterface::InOut){
+    /* NOTE: InOut interfaces have both directions and thus are
+       connected from inter1 to inter2 AND inter2 to inter1
+       Another effect is that a InOut can be connected to/from a single
+       InOut.
+    */
+    if((interThis->getConnectedFrom() == NULL) && (interOther->getConnectedFrom() == NULL)) {
+
+      interOther->connectFrom(interThis);
+      interOther->getConnectedTo().append(interThis);
+      interThis->connectFrom(interOther);
+      interThis->getConnectedTo().append(interOther);
+
+      cout << "connecting 2 InOut"<< endl;
+      return true;
+    }
+    return false;
+  }
+  else if (interThis->getDirection() == interOther->getDirection()) {
+
+    // cannot connect  GI to GI or 2 BI of the same direction.
+    if ((getOwner()->isGroupItem()) && (iface->getOwner()->isGroupItem())) return false;
+    if ((getOwner()->isBoxItem()) && (iface->getOwner()->isBoxItem())) return false;
+
+    if (interThis->getDirection() == AbstractInterface::Input) { // both are inputs
+      cout << "connecting GI to BI" << endl;
+      if(getOwner()->isGroupItem()) {
+        src = interThis;
+        dest = interOther;
+      }
+      else {
+        src = interOther;
+        dest = interThis;
+      }
+    }
+    else { // both are outputs
+      cout << "connecting BO to GO" << endl;
+      if(getOwner()->isGroupItem()){
+        src = interOther;
+        dest = interThis;
+      }
+      else {
+        src = interThis;
+        dest = interOther;
+      }
+    }
+  }
+  else {
+    if ((getOwner()->isGroupItem()) || (iface->getOwner()->isGroupItem())) return false;
+
+    cout << "connecting BO to BI" << endl;
+    if(interOther->getDirection() == AbstractInterface::Output) {
+      src = interOther;
+      dest = interThis;
+    }
+    else {
+      src = interThis;
+      dest = interOther;
+    }
+  }
+
+  if(dest != NULL && src != NULL){
+    // cannot overrive existing connectionFrom
+    if(dest->getConnectedFrom() == NULL) {
+      dest->connectFrom(src);
+      src->connectTo(dest);
+      return true;
+    }
+    else {
+      return false;
+    }
+  }
+  return false;
+}
+
+void InterfaceItem::unconnectTo(InterfaceItem *iface)
+{
+  if(iface->refInter->getConnectedFrom() == refInter){
+    iface->refInter->connectFrom(NULL);
+  }
+  if(iface->refInter->getConnectedTo().contains(refInter)){
+    cout << "abnormal case while removing iface conn from " << qPrintable(name) << " to " << qPrintable(iface->name) << endl;
+    iface->refInter->removeConnectedTo(refInter);
+  }
+  if(refInter->getConnectedFrom() == iface->refInter) {
+    cout << "abnormal case while removing iface conn from " << qPrintable(name) << " to " << qPrintable(iface->name) << endl;
+    refInter->connectFrom(NULL);
+  }
+  if(refInter->getConnectedTo().contains(iface->refInter)){
+    refInter->removeConnectedTo(iface->refInter);
+  }
+}
+
+void InterfaceItem::updatePosition()
+{
+  if(orientation == Parameters::North || orientation == Parameters::South){
+    position = positionRatio * owner->getWidth();
+  } else {
+    position = positionRatio * owner->getHeight();
+  }
+  setOriginPoint();
+}
+
+void InterfaceItem::addConnectionItem(ConnectionItem* item) {
+  connections.append(item);
+}
+
+void InterfaceItem::removeConnectionItem(ConnectionItem* item) {
+  connections.removeOne(item);
+}
+
+QDataStream &operator <<(QDataStream &out, InterfaceItem *i) {
+
+#ifdef DEBUG_INCLFUN
+  out.setVersion(QDataStream::Qt_5);
+
+  QByteArray interfaceData;
+  QDataStream toWrite(&interfaceData, QIODevice::WriteOnly);
+
+  toWrite << i->getId();
+  toWrite << i->getName();
+  toWrite << i->getPositionRatio();
+  toWrite << i->getOrientation();
+
+  foreach(QGraphicsItem* item, i->params->getCurrentScene()->items()){
+    if(item->data(0) == "connection"){
+      ConnectionItem *conn = dynamic_cast<ConnectionItem*>(item);
+      if(conn->getFromInterfaceItem() == i || conn->getToInterfaceItem() == i){
+        toWrite << conn->getId();
+        cout << "id connection : " << conn->getId() << endl;
+      }
+    }
+  }
+  out << interfaceData;
+#endif
+  return out;
+}
+
+QDataStream &operator >>(QDataStream &in, InterfaceItem &i) {
+
+#ifdef DEBUG_INCLFUN
+  in.setVersion(QDataStream::Qt_5);
+
+  int id, orientation;
+  double positionRatio;
+  QString name;
+
+  in >> id;
+  in >> name;
+  in >> positionRatio;
+  in >> orientation;
+
+  i.setId(id);
+  i.setName(name);
+  i.setPositionRatio(positionRatio);
+  i.setOrientation(orientation);
+  i.updatePosition();
+#endif
+  return in;
+}
diff --git a/InterfaceItem.h b/InterfaceItem.h
new file mode 100644 (file)
index 0000000..ce65b9e
--- /dev/null
@@ -0,0 +1,88 @@
+#ifndef __INTERFACEITEM_H__
+#define __INTERFACEITEM_H__
+
+#include <QtCore>
+#include <QtGui>
+
+class Parameters;
+class ConnectedInterface;
+class AbstractBoxItem;
+class ConnectionItem;
+
+
+using namespace std;
+using namespace Qt;
+
+class InterfaceItem {
+
+public:
+
+
+
+  InterfaceItem(double _position,
+                  int _orientation,
+                  ConnectedInterface* _refInter,
+                  AbstractBoxItem* _owner,
+                  Parameters* _params);
+  InterfaceItem();
+  QRectF boundingRect() const;
+  void paint(QPainter *painter);
+
+  // getters
+  inline int getId() { return id; }
+  inline QString getName() { return name; }
+  inline double getPositionRatio() { return positionRatio; }
+  inline double getPosition() { return position; }
+  inline int getOrientation() { return orientation; }
+  inline AbstractBoxItem *getOwner() { return owner; }
+  inline int getNameWidth() { return nameWidth; }
+  inline int getNameHeight() { return nameHeight; }
+  QString getStrOrientation();
+  static int getIntOrientation(QString str);
+  QPointF getEndPointInGroup();
+
+  // setters
+  void setOriginPoint();
+  inline void setId(int id){ this->id = id; }
+  inline void setName(QString name){ this->name = name; }
+  inline void setPositionRatio(double ratio) { positionRatio = ratio; }
+  inline void setOrientation(int _orientation){ orientation = _orientation; }
+
+  // others
+  void addConnectionItem(ConnectionItem* item);
+  void removeConnectionItem(ConnectionItem* item);
+  bool canConnectWith(InterfaceItem* iface);
+  bool connectWith(InterfaceItem* iface);
+  void unconnectTo(InterfaceItem *iface);
+  void updatePosition();
+
+  AbstractBoxItem* owner;
+  ConnectedInterface* refInter;
+  Parameters* params;
+  bool selected;
+  bool visible;
+
+  static int counter;
+
+  QList<ConnectionItem*> connections; // the connection items that are bounded to this interface item
+
+
+private:
+  int id;
+  QString name;
+  double positionRatio;
+  int position; // position in pixels on the "orientation side" of the owner
+  int orientation; // north, south, east, west
+  QPointF originPoint; // the point where starts the drawing (along the box border) NB : in the owner coordinates
+  int nameWidth; // the graphical width of the name, computed from default font metrics
+  int nameHeight; // the graphical height of the name, computed from default font metrics
+
+  friend QDataStream &operator<<(QDataStream &out, InterfaceItem *b);
+  friend QDataStream &operator>>(QDataStream &in, InterfaceItem &b);
+};
+
+/*
+QDataStream & operator <<(QDataStream &out, InterfaceItem *b);
+QDataStream & operator >>(QDataStream &in, InterfaceItem &b);
+*/
+#endif
diff --git a/InterfacePropertiesWindow.cpp b/InterfacePropertiesWindow.cpp
new file mode 100644 (file)
index 0000000..2200bf6
--- /dev/null
@@ -0,0 +1,30 @@
+#include "InterfacePropertiesWindow.h"
+
+#include "ConnectedInterface.h"
+
+InterfacePropertiesWindow::InterfacePropertiesWindow(InterfaceItem *_inter, QWidget *parent) :
+    QWidget(parent)
+{
+  inter = _inter;
+
+  layout = new QGridLayout;
+
+
+  layout->addWidget(new QLabel("Interface properties"), 0, 0);
+  layout->addWidget(new QLabel(" "), 1, 0);
+
+  layout->addWidget(new QLabel("Name :"), 2, 0);
+  layout->addWidget(new QLabel(inter->getName()), 2, 1);
+  layout->addWidget(new QLabel("Width :"), 3, 0);
+  layout->addWidget(new QLabel(inter->refInter->getWidth()), 3, 1);
+  layout->addWidget(new QLabel("Direction :"), 4, 0);
+  layout->addWidget(new QLabel(inter->refInter->getDirectionString()), 4, 1);
+  layout->addWidget(new QLabel("Purpose :"), 5, 0);
+  layout->addWidget(new QLabel(inter->refInter->getPurposeString()), 5, 1);
+  layout->addWidget(new QLabel("Level :"), 6, 0);
+  layout->addWidget(new QLabel(inter->refInter->getLevelString()), 6, 1);
+
+  this->setLayout(layout);
+
+  show();
+}
diff --git a/InterfacePropertiesWindow.h b/InterfacePropertiesWindow.h
new file mode 100644 (file)
index 0000000..3b372a9
--- /dev/null
@@ -0,0 +1,22 @@
+#ifndef __INTERFACEPROPERTIESWINDOW_H__
+#define __INTERFACEPROPERTIESWINDOW_H__
+
+#include <QtWidgets>
+
+#include "InterfaceItem.h"
+
+class InterfacePropertiesWindow : public QWidget
+{
+    Q_OBJECT
+public:
+    explicit InterfacePropertiesWindow(InterfaceItem *_inter, QWidget *parent = 0);
+
+private:
+    QGridLayout *layout;
+    InterfaceItem *inter;
+
+
+
+};
+
+#endif // INTERFACEPROPERTIESWINDOW_H
diff --git a/MainWindow.cpp b/MainWindow.cpp
new file mode 100644 (file)
index 0000000..01c23c1
--- /dev/null
@@ -0,0 +1,399 @@
+#include "MainWindow.h"
+#include "Dispatcher.h"
+#include "Parameters.h"
+#include "BlockLibraryWidget.h"
+#include "GroupWidget.h"
+#include "GroupScene.h"
+#include "BlockWidget.h"
+#include "AbstractBoxItem.h"
+#include "Graph.h"
+#include "GroupItem.h"
+#include <QDomDocument>
+#include <QDomElement>
+#include <QDomText>
+#include <sstream>
+
+MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent) {
+
+  versionMaj = VERSION_MAJ;
+  versionMin = VERSION_MIN;
+  revision = REVISION;
+
+  // reading parameters
+  params  = new Parameters();
+  try {    
+    params->loadBlastConfiguration("blastconfig.xml");
+
+    if (!QFileInfo::exists(params->refLib)) {
+      params->loadReferencesFromXml();
+      int ret = QMessageBox::question(this,tr("Building references library"),tr("The reference block library does not exists.\n References have been read directly from the xml descriptions of blocks.\n It can be saved into a library in order to start application faster. "), QMessageBox::Ok | QMessageBox::Cancel, QMessageBox::Ok);
+      if (ret == QMessageBox::Ok) {
+        params->saveReferencesToLib();
+      }
+    }
+    else {      
+      params->loadReferencesFromLib();
+    }
+
+    if (!QFileInfo::exists(params->implLib)) {
+      params->loadImplementationsFromXml();
+      int ret = QMessageBox::question(this,tr("Building implementations library"),tr("The block implementations library does not exists.\nImplementations have been read directly from the xml descriptions.\n It can be saved into a library in order to start application faster. "), QMessageBox::Ok | QMessageBox::Cancel, QMessageBox::Ok);
+      if (ret == QMessageBox::Ok) {
+        params->saveImplementationsToLib();
+      }
+    }
+    else {
+      params->loadImplementationsFromLib();
+    }
+  }
+  catch(Exception err) {
+    cerr << qPrintable(err.getDefaultMessage()) << endl;
+    cerr << "Aborting ..." << endl;
+    exit(1);
+  }
+
+  cout << "all references and implementations are loaded" << endl;
+
+  // create the menu, action, ...
+  dispatcher = new Dispatcher(params,this);
+  params->setDispatcher(dispatcher);
+
+  // creating block library
+  library = new BlockLibraryWidget(dispatcher,params);
+  isCurrentProject = false;
+
+  QLabel* labDefault = new QLabel("BLAST: BLock ASsembler Tool");
+  stackedWidget = new QStackedWidget;
+  stackedWidget->addWidget(labDefault);
+  stackedWidget->setCurrentIndex(0);
+  this->setCentralWidget(stackedWidget);
+  this->setMinimumSize(800,600);
+
+  createActions();
+  createMenus(); 
+  setWindowTitle("blast - top group");
+  setFocusPolicy(Qt::StrongFocus);
+  setFocus();
+
+  readSettings();
+
+  initialize();
+
+}
+
+MainWindow::~MainWindow() {}
+
+void MainWindow::initialize() {
+
+  projectMenuEnb = 0;
+
+  stackedWidget->setCurrentIndex(0);
+  enableProjectActions(true,PROJECT_NEW | PROJECT_OPEN, OP_RAZ);
+
+  stackedWidget->setCurrentIndex(0);
+
+  resize(500,300);
+}
+
+void MainWindow::readSettings() {
+  QSettings settings;
+  settings.beginGroup("init");
+  checkNewVersion = settings.value("check_new_version").toString();
+  settings.endGroup();
+  if (checkNewVersion.isEmpty()) {
+    checkNewVersion = "true";
+  }
+  /*
+  cout << "test nouvelle version : " << qPrintable(checkNewVersion) << endl;
+  QUrl url("http://www.hrafnheim.fr/download/Cartomagic/carto_currentversion.txt");
+  QNetworkRequest request(url);
+  manager = new QNetworkAccessManager(this);
+  connect(manager,SIGNAL(finished(QNetworkReply*)), this, SLOT(slotCheckNewVersion(QNetworkReply*)));
+  manager->get(request);
+  */
+}
+
+void MainWindow::writeSettings() {
+  QSettings settings;
+  settings.beginGroup("init");
+  settings.setValue("check_new_version",checkNewVersion);
+  settings.endGroup();
+}
+
+void MainWindow::slotCheckNewVersion(QNetworkReply *reply) {
+
+  if (reply->error() == QNetworkReply::NoError) {
+    QString txt = reply->readAll();
+    QString currentVer = QString("%1.%2.%3").arg(versionMaj).arg(versionMin).arg(revision);
+    if (txt.contains(currentVer)) {
+      cout << "a jour" << endl;
+    }
+    else {
+      cout << "dernière version : " << qPrintable(txt) << ", version actuelle = " << qPrintable(currentVer) << endl;
+    }
+  }
+  else {
+    cout << "erreur = " << qPrintable(reply->errorString()) << endl;
+  }
+  reply->deleteLater();
+}
+
+void MainWindow::enableProjectActions(bool enbMenu, quint16 mask, quint8 op) {
+  if (enbMenu) {
+    projectMenu->setEnabled(true);
+  }
+  else {
+    projectMenu->setEnabled(false);
+  }
+
+  if (op == OP_ADD) {
+    projectMenuEnb = projectMenuEnb | mask;
+  }
+  else if (op == OP_REM) {
+    projectMenuEnb = (projectMenuEnb | mask) ^ mask;
+  }
+  else if (op == OP_RAZ) {
+    projectMenuEnb = mask;
+  }
+
+
+  if (projectMenuEnb & PROJECT_NEW) {
+    newProject->setEnabled(true);
+  }
+  else {
+    newProject->setEnabled(false);
+  }
+  if (projectMenuEnb & PROJECT_OPEN) {
+    openProject->setEnabled(true);
+  }
+  else {
+    openProject->setEnabled(false);
+  }
+  if (projectMenuEnb & PROJECT_SAVE) {
+    saveProject->setEnabled(true);
+  }
+  else {
+    saveProject->setEnabled(false);
+  }
+  if (projectMenuEnb & PROJECT_SAVEAS) {
+    saveAsProject->setEnabled(true);
+  }
+  else {
+    saveAsProject->setEnabled(false);
+  }
+  if (projectMenuEnb & PROJECT_CLOSE) {
+    closeProject->setEnabled(true);
+  }
+  else {
+    closeProject->setEnabled(false);
+  }
+  if (projectMenuEnb & PROJECT_LIB) {
+    openLibrary->setEnabled(true);
+  }
+  else {
+    openLibrary->setEnabled(false);
+  }
+}
+
+void MainWindow::createMenus(){
+
+  allMenuBar = menuBar();
+
+  projectMenu = allMenuBar->addMenu(tr("&Project"));
+  toolsMenu = allMenuBar->addMenu(tr("&Tools"));
+
+  projectMenu->addAction(newProject);
+  projectMenu->addAction(openProject);
+  projectMenu->addAction(saveProject);
+  projectMenu->addAction(saveAsProject);
+  projectMenu->addAction(closeProject);
+  projectMenu->addAction(openLibrary);
+
+  toolsMenu->addAction(newBlockWidgetAct);
+  toolsMenu->addAction(graphValidation);
+
+}
+
+void MainWindow::createActions() {
+
+  newProject = new QAction(tr("&New project"), this);
+  newProject->setIcon(QPixmap::fromImage(QImage("icons/new.ico")));
+  newProject->setStatusTip(tr("Create a new project"));
+  connect(newProject, SIGNAL(triggered()), this, SLOT(slotNewProject()));
+
+  openProject = new QAction(tr("&Open project"), this);
+  openProject->setIcon(QPixmap::fromImage(QImage("icons/load.png")));
+  openProject->setStatusTip(tr("Open an existing project"));
+  connect(openProject, SIGNAL(triggered()), this, SLOT(slotLoadProject()));
+
+  saveProject = new QAction(tr("&Save project"), this);
+  saveProject->setIcon(QPixmap::fromImage(QImage("icons/save.png")));
+  saveProject->setStatusTip(tr("Save the current project"));
+  connect(saveProject, SIGNAL(triggered()), this, SLOT(slotSaveProject()));
+
+  saveAsProject = new QAction(tr("&Save project as..."), this);
+  saveAsProject->setIcon(QPixmap::fromImage(QImage("icons/save-as.png")));
+  saveAsProject->setStatusTip(tr("Save the current project as..."));
+  connect(saveAsProject, SIGNAL(triggered()), this, SLOT(slotSaveAsProject()));
+
+  closeProject = new QAction(tr("&Close project"), this);
+  closeProject->setIcon(QPixmap::fromImage(QImage("icons/close.png")));
+  closeProject->setStatusTip(tr("Close the current project"));
+  connect(closeProject, SIGNAL(triggered()), this, SLOT(slotCloseProject()));
+
+  openLibrary = new QAction(tr("Open block &Library"), this);
+  openLibrary->setIcon(QPixmap::fromImage(QImage("icons/add_block.png")));
+  openLibrary->setStatusTip(tr("Open block library window"));
+  connect(openLibrary, SIGNAL(triggered()), this, SLOT(slotOpenBlockLibrary()));
+
+  newBlockWidgetAct = new QAction(tr("&XML generator"), this);
+  newBlockWidgetAct->setIcon(QPixmap::fromImage(QImage("icons/new.ico")));
+  newBlockWidgetAct->setStatusTip(tr("Create a new XML generator"));
+  connect(newBlockWidgetAct, SIGNAL(triggered()), this, SLOT(slotNewBlockWidget()));
+
+  graphValidation = new QAction(tr("&graph validation"), this);
+  graphValidation->setIcon(QPixmap::fromImage(QImage("icons/new.ico")));
+  graphValidation->setStatusTip(tr("validate the graph"));
+  connect(graphValidation, SIGNAL(triggered()), this, SLOT(slotGraphValidation()));
+
+}
+
+void MainWindow::save(QString absoluteFilename) {
+  params->save(absoluteFilename);
+}
+
+void MainWindow::slotLoadProject(){
+
+  absoluteFilename = QFileDialog::getOpenFileName(0, "select a project file", "save/",tr("sauvegardes (*.xml)"));
+
+  if(! absoluteFilename.isEmpty()){
+    GroupWidget* topGroup = dispatcher->loadProject(absoluteFilename);
+    if (topGroup != NULL) {
+      addTopGroup(topGroup);
+    }
+    else {
+      QMessageBox msgBox;
+      msgBox.setText("Cannot open the project.");
+      msgBox.setInformativeText("Do you want to save your changes?");
+      msgBox.setStandardButtons(QMessageBox::Cancel);
+      msgBox.setDefaultButton(QMessageBox::Cancel);
+
+      int ret = msgBox.exec();
+    }
+  }
+}
+
+
+void MainWindow::slotNewProject(){
+
+  enableProjectActions(true, PROJECT_CLOSE | PROJECT_SAVE | PROJECT_SAVEAS | PROJECT_LIB, OP_RAZ);
+  GroupWidget* topGroup = dispatcher->createTopScene();
+  addTopGroup(topGroup);
+
+}
+
+void MainWindow::slotCloseProject(){
+
+  // removing the GroupWidget from stack
+  QWidget *widget = stackedWidget->widget(1);
+  stackedWidget->removeWidget(widget);
+  stackedWidget->setCurrentIndex(0);
+
+  dispatcher->closeCurrentProject();
+
+
+  isCurrentProject = false;
+  params->unsaveModif = false;
+  absoluteFilename = QString();
+
+  initialize();
+}
+
+
+void MainWindow::slotNewBlockWidget() {
+  new BlockWidget();
+}
+
+void MainWindow::slotSaveProject(){
+  if(absoluteFilename != QString()){
+    save(absoluteFilename);
+  } else {
+    slotSaveAsProject();
+  }
+}
+
+void MainWindow::slotSaveAsProject(){
+  if(isCurrentProject){
+    QFileDialog dial(0, "Select a file", "save/");
+    dial.setDefaultSuffix(".xml");
+    dial.setAcceptMode(QFileDialog::AcceptSave);
+    if(dial.exec() == QFileDialog::AcceptSave){
+      absoluteFilename = dial.selectedFiles().at(0);
+      if(absoluteFilename != QString())
+        save(absoluteFilename);
+    }
+  }
+}
+
+void MainWindow::slotOpenBlockLibrary() {
+  dispatcher->showBlocksLibrary();
+}
+
+
+void MainWindow::slotGraphValidation() {
+  params->parametersValidation();
+}
+
+void MainWindow::addTopGroup(GroupWidget *_topGroup) {
+  topGroup = _topGroup;
+  stackedWidget->addWidget(topGroup);
+  stackedWidget->setCurrentIndex(1);
+}
+
+void MainWindow::removeTopGroup() {
+  stackedWidget->removeWidget(topGroup);
+  topGroup->deleteLater();
+  stackedWidget->setCurrentIndex(0);
+}
+
+void MainWindow::closeEvent(QCloseEvent *event){
+  if(isCurrentProject){
+    QMessageBox msgBox;
+    msgBox.setText("The project has been modified.");
+    msgBox.setInformativeText("Do you want to save your changes?");
+    msgBox.setStandardButtons(QMessageBox::Save | QMessageBox::Discard | QMessageBox::Cancel);
+    msgBox.setDefaultButton(QMessageBox::Save);
+
+    int ret = msgBox.exec();
+
+    switch(ret) {
+    case QMessageBox::Save :
+      slotSaveProject();
+      slotCloseProject();
+      break;
+    case QMessageBox::Discard :
+      slotCloseProject();
+      break;
+    }
+    event->ignore();
+  } else {
+    exit(0);
+  }
+}
+
+void MainWindow::mousePressEvent(QMouseEvent *e) {
+
+  if (dispatcher->getCurrentGroup() != NULL) {
+    dispatcher->setCurrentGroupWidget(dispatcher->getCurrentGroup());
+  }
+  QMainWindow::mousePressEvent(e);
+}
+
+void MainWindow::focusInEvent(QFocusEvent *e) {
+/*
+  if(params->currentWindow != this){
+    params->setCurrentWindow(this);
+    changeConnectionMode(false);
+  }
+  */
+}
diff --git a/MainWindow.h b/MainWindow.h
new file mode 100644 (file)
index 0000000..ee51e4c
--- /dev/null
@@ -0,0 +1,128 @@
+#ifndef __MAINWINDOW_H__
+#define __MAINWINDOW_H__
+
+#include <iostream>
+
+#include <QtCore>
+#include <QtGui>
+#include <QtNetwork>
+#include <QtWidgets>
+
+class Dispatcher;
+class Parameters;
+class BlockLibraryWidget;
+class GroupWidget;
+class BlockWidget;
+class Graph;
+
+// versioning related
+#define MAGIC_STRING "opentrace"
+#define VERSION_MAJ (quint8)0 // major version code
+#define VERSION_MIN (quint8)2 // minor version number
+#define REVISION (quint8)1 // revision number of current version
+
+
+// defines for menus
+#define TRACE_MENU (quint8)1
+
+// defines for actions
+#define NONE_ACT (quint16)0
+
+#define PROJECT_NEW (quint16)1
+#define PROJECT_OPEN (quint16)2
+#define PROJECT_SAVE (quint16)4
+#define PROJECT_SAVEAS (quint16)8
+#define PROJECT_CLOSE (quint16)16
+#define PROJECT_LIB (quint16)32
+
+#define OP_ADD (quint8)0
+#define OP_REM (quint8)1
+#define OP_RAZ (quint8)2
+
+using namespace std;
+using namespace Qt;
+
+
+class MainWindow : public QMainWindow {
+
+  Q_OBJECT
+
+public:
+  explicit MainWindow(QWidget *parent = 0);
+  ~MainWindow();
+  void initialize();
+
+  void addTopGroup(GroupWidget* _topGroup);
+  void removeTopGroup(); // called when closing project
+
+
+  inline BlockLibraryWidget *getLibrary(){return library;}
+
+
+protected:
+  void closeEvent(QCloseEvent *);
+  void mousePressEvent(QMouseEvent *e);
+  void focusInEvent(QFocusEvent *e);
+
+private:
+
+  GroupWidget* topGroup;  
+  QStackedWidget *stackedWidget;
+  Dispatcher *dispatcher;
+  Parameters *params;  
+  BlockLibraryWidget *library;
+
+  bool isCurrentProject;
+  QString absoluteFilename;
+
+  QString checkNewVersion;
+
+  void save(QString absoluteFilename);
+
+  void createActions();
+  void createMenus();
+
+  void readSettings();
+  void writeSettings();
+
+  /* Menus */
+  QMenuBar *allMenuBar;
+
+  QMenu* projectMenu;
+  quint16 projectMenuEnb;
+  QMenu* toolsMenu;
+
+  QAction* newProject;
+  QAction* openProject;
+  QAction* saveProject;
+  QAction* saveAsProject;
+  QAction* closeProject;
+  QAction* openLibrary;
+
+  QAction *newBlockWidgetAct;
+  QAction *graphValidation;    
+
+
+  // versioning related
+  quint8 versionMaj;
+  quint8 versionMin;
+  quint8 revision;
+
+public slots:
+  void enableProjectActions(bool enbMenu, quint16 mask = 0, quint8 op = 0); // default : add nothing
+
+private slots:
+  void slotNewProject();
+  void slotLoadProject();
+  void slotSaveProject();
+  void slotSaveAsProject();
+  void slotCloseProject();
+  void slotOpenBlockLibrary();
+
+  void slotNewBlockWidget();  
+  void slotGraphValidation();
+
+  void slotCheckNewVersion(QNetworkReply *reply);
+};
+
+#endif // MAINWINDOW_H
diff --git a/Makefile.in b/Makefile.in
new file mode 100644 (file)
index 0000000..e18672c
--- /dev/null
@@ -0,0 +1,185 @@
+#############################################################################
+# Makefile for building: @@APPNAME@@
+#############################################################################
+
+####### VERSION (modified by the configure script) ############
+APPNAME=@@APPNAME@@
+
+####### VERSION (modified by the configure script) ############
+VERSION=@@APPVER@@
+
+####### OS (modified by the configure script) ############
+OS=@@OS@@
+ARCH=@@ARCH@@
+
+####### Qt (modified by the configure script) ############
+QTVER=@@QTVER@@
+QTPATH=@@QTPATH@@
+
+####### PATHES ############
+BUILDDIR=build
+DISTDIR=dist
+BUILDPATH=$(BUILDDIR)/$(OS)$(ARCH)
+DISTPATH=$(DISTDIR)/$(OS)$(ARCH)/$(APPNAME)-$(VERSION)
+ARDIR=archive
+ARPATH=$(ARDIR)/$(APPNAME)/v$(VERSION)
+
+####### COMPILERS ############
+CC-lin32        = gcc
+CXX-lin32       = g++
+CC-lin64        = gcc
+CXX-lin64       = g++
+CC-win32        = i686-w64-mingw32-gcc-win32
+CXX-win32       = i686-w64-mingw32-g++-win32
+WINDRES-win32   = i686-w64-mingw32-windres
+CC-win64        = x86_64-w64-mingw32-gcc-win32
+CXX-win64       = x86_64-w64-mingw32-g++-win32
+WINDRES-win64   = x86_64-w64-mingw32-windres
+
+CC           = $(CC-$(OS)$(ARCH))
+CXX          = $(CXX-$(OS)$(ARCH))
+WINDRES       = $(WINDRES-$(OS)$(ARCH))
+
+DEFINES-lin32     = -DDEBUG  -DQT_NO_DEBUG -DQT_XML_LIB -DQT_GUI_LIB -DQT_CORE_LIB -DQT_SHARED -D@@APPDEF@@_LIN
+DEFINES-lin64     = -DDEBUG  -DQT_NO_DEBUG -DQT_XML_LIB -DQT_GUI_LIB -DQT_CORE_LIB -DQT_SHARED -D@@APPDEF@@_LIN
+DEFINES-win32     = -DUNICODE -DQT_LARGEFILE_SUPPORT -DQT_DLL -DQT_NO_DEBUG -DQT_HAVE_MMX -DQT_HAVE_3DNOW -DQT_HAVE_SSE -DQT_HAVE_MMXEXT -DQT_HAVE_SSE2 -DQT_THREAD_SUPPORT -DQT_NEEDS_QMAIN -DQT_AXCONTAINER_LIB -DQT_PRINTSUPPORT_LIB -DQT_AXBASE_LIB -DQT_WIDGETS_LIB -DQT_GUI_LIB -DQT_CORE_LIB -DQT_XML_LIB -D@@APPDEF@@_WIN
+
+DEFINES       = $(DEFINES-$(OS)$(ARCH))
+
+CFLAGS-lin32      = @@DEBUG@@ -pipe -O2 -Wall -fPIC -D_REENTRANT $(DEFINES)
+CFLAGS-lin64      = @@DEBUG@@ -pipe -O2 -Wall -fPIC -D_REENTRANT $(DEFINES)
+CXXFLAGS-lin32    = @@DEBUG@@ -pipe -O2 -Wall -fPIC -D_REENTRANT $(DEFINES)
+CXXFLAGS-lin64    = @@DEBUG@@ -pipe -O2 -Wall -fPIC -D_REENTRANT $(DEFINES)
+CFLAGS-win32      = @@DEBUG@@ -pipe -fno-keep-inline-dllexport -O2 -Wall -Wextra $(DEFINES)
+CXXFLAGS-win32    = @@DEBUG@@ -pipe -fno-keep-inline-dllexport -O2 -frtti -Wall -Wextra -fexceptions -mthreads $(DEFINES)
+
+CFLAGS       = $(CFLAGS-$(OS)$(ARCH))
+CXXFLAGS     = $(CXXFLAGS-$(OS)$(ARCH))
+
+INCPATH-lin64-qt4       = -I/usr/share/qt4/mkspecs/linux-g++ -I$(QTPATH)/QtCore -I$(QTPATH)/QtGui -I$(QTPATH)/QtNetwork -I$(QTPATH)/QtXml -I$(QTPATH)/QtXmlPatterns -I$(QTPATH)
+INCPATH-lin64-qt5       = -I$(QTPATH)/mkspecs/linux-g++-64 -I$(QTPATH) -I$(QTPATH)/QtWidgets -I$(QTPATH)/QtCore -I$(QTPATH)/QtGui -I$(QTPATH)/QtPrintSupport -I$(QTPATH)/QtNetwork -I$(QTPATH)/QtXml -I$(QTPATH)/QtXmlPatterns 
+INCPATH-win32-qt5       = -I$(QTPATH)/mkspecs/win32-g++ -I$(QTPATH)/include -I$(QTPATH)/include/ActiveQt -I$(QTPATH)/include/QtWidgets -I$(QTPATH)/include/QtGui -I$(QTPATH)/include/QtCore -I$(QTPATH)/include/QtXml -I$(QTPATH)/include/QtXmlPatterns -I$(QTPATH)/include/QtPrintSupport
+
+INCPATH       = $(INCPATH-$(OS)$(ARCH)-qt$(QTVER)) -I.
+
+################## LINKER #####################
+LINK-lin32        = g++
+LINK-lin64        = g++
+LINK-win32       = i686-w64-mingw32-g++-win32
+LINK-win64       = x86_64-w64-mingw32-g++-win32
+
+LINK     = $(LINK-$(OS)$(ARCH))
+
+LFLAGS-lin32        =  -m32 -Wl,-O1
+LFLAGS-lin64        =  -m64 -Wl,-O1
+LFLAGS-win32        = -Wl,-s -mthreads -Wl,-subsystem,console -mthreads -static-libgcc -static-libstdc++
+LFLAGS-win64        = -Wl,-s -mthreads -Wl,-subsystem,console -mthreads -static-libgcc -static-libstdc++
+
+LFLAGS     = $(LFLAGS-$(OS)$(ARCH))
+
+LIBS-lin64-qt4  = -lQtCore -lQtGui -lQtXml -lQtXmlPatterns -lpthread -lm
+LIBS-lin64-qt5  = -lQt5Core -lQt5Gui -lQt5Xml -lQt5XmlPatterns -lQt5Widgets -lQt5PrintSupport -lQt5Network -lpthread -lm
+LIBS-win32-qt5  =  -lmingw32 -L$(QTPATH)/lib -lqtmain -lQt5AxContainer -lQt5PrintSupport -lQt5AxBase -lglu32 -lopengl32 -lole32 -loleaut32 -luser32 -lgdi32 -ladvapi32 -luuid -lQt5Widgets -lQt5Gui -lQt5Core -lQt5Xml -lQt5XmlPatterns -lQt5Network -lm -lws2_32
+
+LIBS          = $(LIBS-$(OS)$(ARCH)-qt$(QTVER))
+
+################## OBJECTS #####################
+include object-files.txt
+
+OBJ-lin           = $(COMMON-OBJ)
+OBJ-win           = $(COMMON-OBJ) $(BUILDPATH)/$(APPNAME)_res.o
+
+OBJ    = $(OBJ-$(OS))
+
+################## EXECUTBALE ####################
+EXENAME-lin    = $(APPNAME)
+EXENAME-win    = $(APPNAME).exe
+
+EXENAME = $(EXENAME-$(OS))
+
+all: $(BUILDPATH)/$(EXENAME)
+
+$(BUILDPATH)/$(EXENAME) : $(OBJ)
+       $(LINK) $(LFLAGS) -o $@ $^ $(LIBS)
+       cp $(BUILDPATH)/$(EXENAME) .
+
+$(BUILDPATH)/$(APPNAME)_res.o: $(APPNAME).rc
+       $(WINDRES) -i $(APPNAME).rc -o $(BUILDPATH)/$(APPNAME)_res.o --include-dir=. $(DEFINES)
+
+################## DISTRIBUTION ARCHIVE #####################
+DISTNAME = dist-$(OS)
+
+dist : $(DISTNAME)
+
+dist-lin: $(BUILDPATH)/$(APPNAME)
+       @echo -n creating binary distribution archive for Linux ...
+       @-rm -rf $(DISTPATH)
+       @-mkdir -p $(DISTPATH)
+       @-mkdir -p $(DISTPATH)/locales
+       @cp $(BUILDPATH)/$(APPNAME) $(DISTPATH)
+       @if ls $(APPNAME)_*.qm 2>/dev/null 1>&2; then for loc in $(APPNAME)_*.qm; do cp $$loc $(DISTPATH)/locales; done; fi
+       @cp install.sh $(DISTPATH)
+       @if [ -d examples ]; then cp -r examples $(DISTPATH); fi
+       @cd $(DISTPATH); cd ..; tar zcf $(APPNAME)-$(VERSION)_$(OS)$(ARCH).tgz $(APPNAME)-$(VERSION); rm -rf $(APPNAME)-$(VERSION)
+       @echo done; echo result is in $(DISTDIR)/$(OS)$(ARCH)/$(APPNAME)-$(VERSION)_$(OS)$(ARCH).tgz
+
+dist-win: $(BUILDPATH)/$(EXENAME)
+       @echo -n creating binary distribution archive for Windows ...
+       @rm -rf $(DISTPATH)
+       @mkdir -p $(DISTPATH)
+       @cp $(BUILDPATH)/$(APPNAME).exe $(DISTPATH)
+       @cp -r lib/$(OS)$(ARCH)/* $(DISTPATH)
+       @if ls $(APPNAME)_*.qm 2>/dev/null 1>&2; then for loc in $(APPNAME)_*.qm; do cp $$loc $(DISTPATH); done; fi
+       @if [ -d examples ]; then cp -r examples $(DISTPATH); fi
+       @cd $(DISTPATH); cd ..; zip -r $(APPNAME)-$(VERSION)_$(OS)$(ARCH).zip $(APPNAME)-$(VERSION)/* ; rm -rf $(APPNAME)-$(VERSION)
+       @echo done; echo result is in $(DISTDIR)/$(OS)$(ARCH)/$(APPNAME)-$(VERSION)_$(OS)$(ARCH).zip
+
+src-dist:
+       @echo -n creating source archive ...
+       @rm -rf $(ARPATH)
+       @mkdir -p $(ARPATH)
+       @cp *.cpp $(ARPATH)
+       @cp *.h $(ARPATH)
+# copying various files: translations (.ts), locales (.qm), resources (.qrc), xml related (.xml,.xsd), config. files (.conf) ...
+       @if ls $(APPNAME)_*.ts 2>/dev/null 1>&2; then for loc in $(APPNAME)_*.ts; do cp $$loc $(ARPATH); done; fi
+       @if ls $(APPNAME)_*.qm 2>/dev/null 1>&2; then for loc in $(APPNAME)_*.qm; do cp $$loc $(ARPATH); done; fi
+       @if ls *.conf 2>/dev/null 1>&2; then for loc in *.conf; do cp $$loc $(ARPATH); done; fi
+       @if ls *.xml 2>/dev/null 1>&2; then for loc in *.xml; do cp $$loc $(ARPATH); done; fi
+       @if ls *.xsd 2>/dev/null 1>&2; then for loc in *.xsd; do cp $$loc $(ARPATH); done; fi
+       @if [ -f $(APPNAME).qrc ]; then cp $(APPNAME).qrc $(ARPATH); fi
+       @if [ -d icons ]; then cp -r icons $(ARPATH); fi
+       @if [ -d examples ]; then cp -r examples $(ARPATH); fi
+       @cp -r lib $(ARPATH)
+       @cp install.sh.in $(ARPATH)
+       @cp Makefile.in $(ARPATH)
+       @cp object-files.txt $(ARPATH)
+       @cp configure $(ARPATH)
+       @if [ -f $(APPNAME).rc ]; then cp $(APPNAME).rc $(ARPATH); fi
+       @if [ -f $(APPNAME).ico ]; then cp $(APPNAME).ico $(ARPATH); fi
+       @cp $(APPNAME).creator $(ARPATH)
+       @if [ -f $(APPNAME).creator.user ]; then cp $(APPNAME).creator.user $(ARPATH); fi
+       @cp $(APPNAME).files $(ARPATH)
+       @cp $(APPNAME).includes $(ARPATH)
+       @if [ -f $(APPNAME).config ]; then cp $(APPNAME).config $(ARPATH); fi
+       @cd $(ARPATH); cd ../..; tar zcf $(APPNAME)-$(VERSION)-src.tgz $(APPNAME); rm -rf $(APPNAME)
+       @echo done; echo result is in $(ARDIR)/$(APPNAME)-$(VERSION)-src.zip
+clean:
+       rm -f $(OBJ)
+       rm -f *~
+       rm -f moc_*.cpp
+       rm -f rcc_*.cpp
+       rm -f $(BUILDPATH)/$(EXENAME)
+       rm -f $(EXENAME)        
+
+### NEW RULES ###
+$(BUILDPATH)/%.o : %.cpp
+       $(CXX) -c $(CXXFLAGS) $(INCPATH) -o $@ $<
+
+moc_%.cpp : %.h
+       moc -qt=$(QTVER) $(DEFINES) $(INCPATH) $< -o $@
+
+rcc_%.cpp : %.qrc
+       rcc -qt=$(QTVER) $< -o $@ -name $*
+
+### DEPENDENCIES OF EACH SOURCE FILE (auto-added by configure) ###
+
diff --git a/Parameters.cpp b/Parameters.cpp
new file mode 100644 (file)
index 0000000..c991e5f
--- /dev/null
@@ -0,0 +1,1220 @@
+#include "Parameters.h"\r
+\r
+#include "Dispatcher.h"\r
+#include "BlockLibraryTree.h"\r
+\r
+#include "BlockCategory.h"\r
+\r
+#include "GroupWidget.h"\r
+#include "GroupScene.h"\r
+#include "GroupItem.h"\r
+#include "BoxItem.h"\r
+#include "InterfaceItem.h"\r
+#include "ConnectionItem.h"\r
+\r
+#include "Graph.h"\r
+#include "ReferenceBlock.h"\r
+#include "GroupBlock.h"\r
+#include "FunctionalBlock.h"\r
+#include "ReferenceInterface.h"\r
+#include "GroupInterface.h"\r
+#include "FunctionalInterface.h"\r
+\r
+#include "Exception.h"\r
+#include "BlocksToConfigureWidget.h"\r
+\r
+Parameters::Parameters() {\r
+  categoryTree = NULL;\r
+  arrowWidth = 5;\r
+  arrowHeight = 10;\r
+  arrowLineLength = 10;\r
+\r
+  defaultBlockWidth = 100;\r
+  defaultBlockHeight = 100;\r
+  defaultBlockFont = QFont("Arial");\r
+  defaultBlockFontSize = 12;\r
+\r
+  setArrowPathes();\r
+\r
+  sceneMode = MODE_EDITION; // default mode\r
+  editState = Parameters::EditNoOperation;\r
+\r
+  unsaveModif = false;\r
+  isRstClkShown = false;\r
+\r
+  projectPath = QDir::currentPath();\r
+}\r
+\r
+Parameters::~Parameters() {\r
+  clear();\r
+}\r
+\r
+void Parameters::clear() {\r
+  delete categoryTree;\r
+  QListIterator<ReferenceBlock *> iter(availableBlocks);\r
+  while(iter.hasNext()) {\r
+    ReferenceBlock* item = iter.next();\r
+    delete item;\r
+  }\r
+  availableBlocks.clear();\r
+  refPathes.clear();\r
+}\r
+\r
+Graph* Parameters::createGraph() {\r
+  graph = new Graph();\r
+  return graph;\r
+}\r
+\r
+void Parameters::destroyGraph() {\r
+  delete graph;\r
+}\r
+\r
+GroupBlock* Parameters::addGroupBlock() {\r
+  GroupBlock* parent = AB_TO_GRP(currentScene->getGroupItem()->getRefBlock());\r
+  GroupBlock* newOne = graph->createChildBlock(parent);\r
+  return newOne;\r
+}\r
+\r
+FunctionalBlock* Parameters::addFunctionalBlock(int idCategory, int idBlock) {\r
+\r
+  BlockCategory* blockCat = categoryTree->searchCategory(idCategory);\r
+\r
+  if (blockCat == NULL) return NULL;\r
+  GroupBlock* group = AB_TO_GRP(currentScene->getGroupItem()->getRefBlock());\r
+  ReferenceBlock* ref = blockCat->getBlock(idBlock);\r
+  if (ref == NULL) return NULL;\r
+\r
+  FunctionalBlock* newOne = graph->addFunctionalBlock(group, ref);\r
+  unsaveModif = true;\r
+\r
+  return newOne;\r
+}\r
+\r
+FunctionalBlock* Parameters::duplicateFunctionalBlock(FunctionalBlock *block) {\r
+\r
+  ReferenceBlock* ref = block->getReference();\r
+  GroupBlock* group = AB_TO_GRP(block->getParent());\r
+\r
+  // adding to the group\r
+  FunctionalBlock* newBlock = new FunctionalBlock(group,ref);\r
+  newBlock->populate();\r
+  group->addBlock(newBlock);\r
+\r
+  return newBlock;\r
+}\r
+\r
+void Parameters::validateXmlFile(const QString& xmlFileName, const QString& xsdFileName, XmlFileType fileType) throw(Exception) {\r
+  // opening configFile\r
+  QFile xmlFile(xmlFileName);\r
+  if (!xmlFile.open(QIODevice::ReadOnly)) {\r
+    if (fileType == Configuration) {\r
+      throw(Exception(CONFIGFILE_NOACCESS));\r
+    }\r
+    else if (fileType == Reference) {\r
+      throw(Exception(BLOCKFILE_NOACCESS));\r
+    }\r
+    else if (fileType == Implementation) {\r
+      throw(Exception(IMPLFILE_NOACCESS));\r
+    }\r
+    else if (fileType == Project) {\r
+      throw(Exception(PROJECTFILE_NOACCESS));\r
+    }\r
+  }\r
+\r
+  QFile xsdFile(xsdFileName);\r
+  if (!xsdFile.open(QIODevice::ReadOnly)) {\r
+    xsdFile.close();\r
+    if (fileType == Configuration) {\r
+      throw(Exception(CONFIGFILE_NOACCESS));\r
+    }\r
+    else if (fileType == Reference) {\r
+      throw(Exception(BLOCKFILE_NOACCESS));\r
+    }\r
+    else if (fileType == Implementation) {\r
+      throw(Exception(IMPLFILE_NOACCESS));\r
+    }\r
+    else if (fileType == Project) {\r
+      throw(Exception(PROJECTFILE_NOACCESS));\r
+    }\r
+  }\r
+\r
+  if(validate(xmlFile,xsdFile) == false) {\r
+    xmlFile.close();\r
+    xsdFile.close();\r
+    if (fileType == Configuration) {\r
+      throw(Exception(CONFIGFILE_CORRUPTED));\r
+    }\r
+    else if (fileType == Reference) {\r
+      throw(Exception(BLOCKFILE_CORRUPTED));\r
+    }\r
+    else if (fileType == Implementation) {\r
+      throw(Exception(IMPLFILE_CORRUPTED));\r
+    }\r
+    else if (fileType == Project) {\r
+      throw(Exception(PROJECTFILE_CORRUPTED));\r
+    }\r
+  }\r
+  xmlFile.close();\r
+  xsdFile.close();\r
+}\r
+\r
+bool Parameters::validate(QFile& fileXml, QFile& fileSchema) {\r
+\r
+  // 2 files are supposed to be already opened\r
+  QXmlSchema schema;\r
+\r
+  if(! schema.load(&fileSchema)){\r
+    cout << "invalid schema" << endl;\r
+    return false;\r
+  }\r
+\r
+  QXmlSchemaValidator validator(schema);\r
+\r
+  if(! validator.validate(&fileXml)){\r
+    cout << "invalid xml" << endl;\r
+    return false;\r
+  }\r
+  return true;\r
+}\r
+\r
+QDomElement Parameters::openProjectFile(const QString& projectFileName) throw(Exception) {\r
+\r
+  try {\r
+    validateXmlFile(projectFileName,"projectfile.xsd",Project);\r
+  }\r
+  catch(Exception err) {\r
+    throw(err);\r
+  }\r
+\r
+  QFile projectFile(projectFileName);\r
+  QDomDocument doc("projectFile");\r
+\r
+  if(!projectFile.open(QIODevice::ReadOnly)) {\r
+    throw(Exception(PROJECTFILE_NOACCESS));\r
+  }\r
+  if(!doc.setContent(&projectFile)) {\r
+    projectFile.close();\r
+    throw(Exception(PROJECTFILE_CORRUPTED));\r
+  }\r
+  projectFile.close();\r
+\r
+  QDomElement root = doc.documentElement();\r
+\r
+  return root;\r
+}\r
+\r
+void Parameters::loadProject(QDomElement root) {\r
+\r
+#ifdef DEBUG_INCLFUN\r
+\r
+  bool ok = false;\r
+  GroupWidget* groupWidget = NULL;\r
+  GroupItem *groupItem = NULL;\r
+  GroupBlock *groupBlock = NULL;\r
+\r
+  /**********************************************************\r
+   1 : getting scene and creating associated group widgets\r
+  ***********************************************************/\r
+  QDomNodeList scenesNodes = root.elementsByTagName("scene");\r
+\r
+  for(int i=0; i<scenesNodes.length(); i++) {\r
+    QDomElement currentSceneNode = scenesNodes.at(i).toElement();\r
+    int idScene = currentSceneNode.attribute("id","none").toInt(&ok);\r
+    if(!ok) throw(Exception(PROJECTFILE_CORRUPTED));\r
+    int idUpperScene = currentSceneNode.attribute("upper_scene","none").toInt(&ok);\r
+    if(!ok) throw(Exception(PROJECTFILE_CORRUPTED));\r
+\r
+    if (idUpperScene == -1) {\r
+      dispatcher->createTopScene();\r
+      topScene->setId(idScene);\r
+      groupItem = topScene->getGroupItem();\r
+      groupBlock = AB_TO_GRP(groupItem->getRefBlock());\r
+      cout << "top group added to scene n°" << idScene << endl;\r
+    }\r
+    else {\r
+      GroupScene* scene = searchSceneById(idUpperScene, topScene);\r
+      GroupWidget* parent = scene->getGroupWindow();\r
+      groupWidget = dispatcher->createChildScene(parent);\r
+      groupItem = groupWidget->getScene()->getGroupItem();\r
+      groupBlock = AB_TO_GRP(groupItem->getRefBlock());\r
+    }\r
+    /**********************************************************\r
+     1.1 : getting the group item\r
+    ***********************************************************/\r
+    QDomElement groupItemNode = currentSceneNode.firstChildElement("group_item");\r
+\r
+    int id = groupItemNode.attribute("id","none").toInt(&ok);\r
+    if(!ok) throw(Exception(PROJECTFILE_CORRUPTED));\r
+\r
+    QString name = groupItemNode.attribute("name","none");\r
+    if(name == "none") throw(Exception(PROJECTFILE_CORRUPTED));\r
+\r
+    QStringList positionStr = groupItemNode.attribute("position","none").split(",");\r
+    if(positionStr.length() != 2) throw(Exception(PROJECTFILE_CORRUPTED));\r
+    int posX = positionStr.at(0).toInt(&ok);\r
+    if(!ok) throw(Exception(PROJECTFILE_CORRUPTED));\r
+    int posY = positionStr.at(1).toInt(&ok);\r
+    if(!ok) throw(Exception(PROJECTFILE_CORRUPTED));\r
+\r
+    QStringList dimensionStr = groupItemNode.attribute("dimension","none").split(",");\r
+    if(dimensionStr.length() != 2) throw(Exception(PROJECTFILE_CORRUPTED));\r
+    int dimX = dimensionStr.at(0).toInt(&ok);\r
+    if(!ok) throw(Exception(PROJECTFILE_CORRUPTED));\r
+    int dimY = dimensionStr.at(1).toInt(&ok);\r
+    if(!ok) throw(Exception(PROJECTFILE_CORRUPTED));\r
+\r
+    groupItem->setId(id);\r
+    groupItem->setPos(posX,posY);\r
+    groupItem->setDimension(dimX,dimY);\r
+    groupBlock->setName(name);\r
+\r
+    if (idUpperScene != -1) {\r
+      groupWidget->setWindowTitle(groupBlock->getName());\r
+      groupWidget->show();\r
+    }\r
+    cout << "group info : \n-id : " << id << "\n-pos : " << posX << ", " << posY << "\n-dim : " << dimX << ", " << dimY << "\n-name : " << name.toStdString() << endl;\r
+\r
+    QDomNodeList interfaces = groupItemNode.elementsByTagName("group_iface");\r
+    for(int j=0; j<interfaces.length(); j++){\r
+      QDomElement currentInterfaceNode = interfaces.at(j).toElement();\r
+\r
+      int id = currentInterfaceNode.attribute("id","none").toInt(&ok);\r
+      if(!ok) throw(Exception(PROJECTFILE_CORRUPTED));\r
+\r
+      QString name = currentInterfaceNode.attribute("name","none");\r
+      if(name == "none") throw(Exception(PROJECTFILE_CORRUPTED));\r
+\r
+      QString levelStr = currentInterfaceNode.attribute("level","none");\r
+      int level = AbstractInterface::getIntLevel(levelStr);\r
+      if(level == -1) throw(Exception(PROJECTFILE_CORRUPTED));\r
+\r
+      QString directionStr = currentInterfaceNode.attribute("direction","none");\r
+      int direction = AbstractInterface::getIntDirection(directionStr);\r
+      if(direction == -1) throw(Exception(PROJECTFILE_CORRUPTED));\r
+\r
+      QString orientationStr = currentInterfaceNode.attribute("orientation","none");\r
+      int orientation = InterfaceItem::getIntOrientation(orientationStr);\r
+      if(orientation == -1) throw(Exception(PROJECTFILE_CORRUPTED));\r
+\r
+      double position = currentInterfaceNode.attribute("position","none").toDouble(&ok);\r
+      if(!ok) throw(Exception(PROJECTFILE_CORRUPTED));\r
+\r
+      GroupInterface *groupInterface = new GroupInterface(groupBlock,name,direction,level);\r
+\r
+      InterfaceItem *interfaceItem = new InterfaceItem(position,orientation,groupInterface,groupItem,this);\r
+      interfaceItem->setId(id);\r
+\r
+      groupBlock->addInterface(groupInterface);\r
+      groupItem->addInterface(interfaceItem);\r
+      cout << "interface add to " << groupBlock->getName().toStdString() << endl;\r
+    }\r
+  }\r
+\r
+  cout << "groupItems loaded and windows created succefully!" << endl;\r
+\r
+\r
+  for(int i=0; i<scenesNodes.length(); i++){\r
+    QDomElement currentSceneNode = scenesNodes.at(i).toElement();\r
+    int idScene = currentSceneNode.attribute("id","none").toInt(&ok);\r
+    if(!ok) throw(Exception(PROJECTFILE_CORRUPTED));\r
+    cout << "SCENE : " << idScene << endl;\r
+    GroupScene *currentScene = searchSceneById(idScene,topScene);\r
+\r
+    if(currentScene == NULL) throw(Exception(PROJECTFILE_CORRUPTED));\r
+\r
+    QDomNodeList functionalBlockNodes = currentSceneNode.elementsByTagName("bi_functional");\r
+\r
+    for(int j=0; j<functionalBlockNodes.length(); j++){\r
+      QDomElement currentFBNode = functionalBlockNodes.at(j).toElement();\r
+\r
+      int id = currentFBNode.attribute("id","none").toInt(&ok);\r
+      if(!ok) throw(Exception(PROJECTFILE_CORRUPTED));\r
+\r
+      QString refXml = currentFBNode.attribute("ref_xml","none");\r
+      if(refXml == "none") throw(Exception(PROJECTFILE_CORRUPTED));\r
+\r
+      QString refMd5 = currentFBNode.attribute("ref_md5","none");\r
+      if(refMd5 == "none") throw(Exception(PROJECTFILE_CORRUPTED));\r
+\r
+      cout << "ref md5 : " << refMd5.toStdString() << "\nref xml : " << refXml.toStdString() << endl;\r
+\r
+      QString name = currentFBNode.attribute("name","none");\r
+      if(name == "none") throw(Exception(PROJECTFILE_CORRUPTED));\r
+\r
+      QStringList positionStr = currentFBNode.attribute("position","none").split(",");\r
+      if(positionStr.length() != 2) throw(Exception(PROJECTFILE_CORRUPTED));\r
+      int posX = positionStr.at(0).toInt(&ok);\r
+      if(!ok) throw(Exception(PROJECTFILE_CORRUPTED));\r
+      int posY = positionStr.at(1).toInt(&ok);\r
+      if(!ok) throw(Exception(PROJECTFILE_CORRUPTED));\r
+\r
+      QStringList dimensionStr = currentFBNode.attribute("dimension","none").split(",");\r
+      if(dimensionStr.length() != 2) throw(Exception(PROJECTFILE_CORRUPTED));\r
+      int dimX = dimensionStr.at(0).toInt(&ok);\r
+      if(!ok) throw(Exception(PROJECTFILE_CORRUPTED));\r
+      int dimY = dimensionStr.at(1).toInt(&ok);\r
+      if(!ok) throw(Exception(PROJECTFILE_CORRUPTED));\r
+\r
+      AbstractBlock *reference;\r
+      /*if(refMd5 != "none"){\r
+        cout << "md5" << endl;\r
+        reference = searchBlockByMd5(refMd5);\r
+      }\r
+      else */if(refXml != "none"){\r
+        cout << "xml" << endl;\r
+        reference = searchBlockByXml(refXml);\r
+      }\r
+      else {\r
+        throw(Exception(PROJECTFILE_CORRUPTED));\r
+      }\r
+\r
+      FunctionalBlock *functionalBlock = new FunctionalBlock(currentScene->getGroupItem()->getRefBlock(),reference);\r
+      functionalBlock->setName(name);\r
+\r
+      ((GroupBlock*)currentScene->getGroupItem()->getRefBlock())->addBlock(functionalBlock);\r
+\r
+\r
+      BlockItem *blockItem = new BlockItem(currentScene->getGroupItem(),functionalBlock,dispatcher,this);\r
+      blockItem->setPos(posX,posY);\r
+      blockItem->setDimension(dimX,dimY);\r
+      blockItem->setId(id);\r
+      ((GroupItem*)currentScene->getGroupItem())->addBlockItem(blockItem);\r
+      currentScene->addItem(blockItem);\r
+      currentScene->addBlockItem(blockItem);\r
+\r
+      QDomNodeList blockParamNodes = currentFBNode.elementsByTagName("bif_parameter");\r
+\r
+      for(int i=0; i<blockParamNodes.length(); i++){\r
+        QDomElement currentBlockParamNode = blockParamNodes.at(i).toElement();\r
+\r
+        QString name = currentBlockParamNode.attribute("name","none");\r
+        if(name == "none") throw(Exception(PROJECTFILE_CORRUPTED));\r
+\r
+        QString value = currentBlockParamNode.attribute("value","none");\r
+        if(value == "none") throw(Exception(PROJECTFILE_CORRUPTED));\r
+\r
+        QString context = currentBlockParamNode.attribute("context","none");\r
+        if(context == "none") throw(Exception(PROJECTFILE_CORRUPTED));\r
+\r
+        QString type = currentBlockParamNode.attribute("type","none");\r
+        if(type == "none") throw(Exception(PROJECTFILE_CORRUPTED));\r
+\r
+\r
+        BlockParameter *blockParam = new BlockParameter;\r
+        blockParam->setName(name);\r
+        blockParam->setValue(value);\r
+        blockParam->setType(type);\r
+        if(context == "constant") blockParam->setContext(BlockParameter::Constant);\r
+        if(context == "user") blockParam->setContext(BlockParameter::User);\r
+        if(context == "generic") blockParam->setContext(BlockParameter::Generic);\r
+        if(context == "wb") blockParam->setContext(BlockParameter::Wishbone);\r
+        if(context == "port") blockParam->setContext(BlockParameter::Port);\r
+\r
+        functionalBlock->addParameter(blockParam);\r
+      }\r
+\r
+\r
+      QDomNodeList interfaceNodes = currentFBNode.elementsByTagName("bif_iface");\r
+\r
+      for(int i=0; i<interfaceNodes.length(); i++){\r
+\r
+        QDomElement currentInterfaceNode = interfaceNodes.at(i).toElement();\r
+\r
+        int id = currentInterfaceNode.attribute("id","none").toInt(&ok);\r
+        if(!ok) throw(Exception(PROJECTFILE_CORRUPTED));\r
+\r
+        QString name = currentInterfaceNode.attribute("name","none");\r
+        if(name == "none") throw(Exception(PROJECTFILE_CORRUPTED));\r
+\r
+        QString refName = currentInterfaceNode.attribute("ref_name","none");\r
+        if(refName == "none") throw(Exception(PROJECTFILE_CORRUPTED));\r
+\r
+        QString orientationStr = currentInterfaceNode.attribute("orientation","none");\r
+        int orientation = InterfaceItem::getIntOrientation(orientationStr);\r
+        if(orientation == -1) throw(Exception(PROJECTFILE_CORRUPTED));\r
+\r
+        double position = currentInterfaceNode.attribute("position","none").toDouble(&ok);\r
+        if(!ok) throw(Exception(PROJECTFILE_CORRUPTED));\r
+\r
+        ReferenceInterface *refInter = (ReferenceInterface*)reference->getIfaceFromName(refName);\r
+        FunctionalInterface *functionalInterface = new FunctionalInterface(functionalBlock,refInter);\r
+        functionalBlock->addInterface(functionalInterface);\r
+        functionalInterface->setName(refName);\r
+\r
+        InterfaceItem *interfaceItem = new InterfaceItem(position,orientation,functionalInterface,blockItem,this);\r
+        interfaceItem->setId(id);\r
+        interfaceItem->setName(name);\r
+\r
+        blockItem->addInterface(interfaceItem);\r
+\r
+      }\r
+    }\r
+  }\r
+  cout << "functionalBlocks loaded and created succefully!" << endl;\r
+\r
+\r
+  for(int i=0; i<scenesNodes.length(); i++){\r
+    QDomElement currentSceneNode = scenesNodes.at(i).toElement();\r
+    int idScene = currentSceneNode.attribute("id","none").toInt(&ok);\r
+    if(!ok) throw(Exception(PROJECTFILE_CORRUPTED));\r
+    GroupScene *currentScene = searchSceneById(idScene, topScene);\r
+    if(currentScene == NULL) throw(Exception(PROJECTFILE_CORRUPTED));\r
+\r
+    QDomNodeList biGroupNodes = currentSceneNode.elementsByTagName("bi_group");\r
+\r
+    for(int j=0; j<biGroupNodes.length(); j++){\r
+      QDomElement currentBiGroup = biGroupNodes.at(j).toElement();\r
+\r
+      int id = currentBiGroup.attribute("id","none").toInt(&ok);\r
+      if(!ok) throw(Exception(PROJECTFILE_CORRUPTED));\r
+\r
+      int idGroup = currentBiGroup.attribute("inside_group","none").toInt(&ok);\r
+      if(!ok) throw(Exception(PROJECTFILE_CORRUPTED));\r
+\r
+      QStringList positionStr = currentBiGroup.attribute("position","none").split(",");\r
+      if(positionStr.length() != 2) throw(Exception(PROJECTFILE_CORRUPTED));\r
+      int posX = positionStr.at(0).toInt(&ok);\r
+      if(!ok) throw(Exception(PROJECTFILE_CORRUPTED));\r
+      int posY = positionStr.at(1).toInt(&ok);\r
+      if(!ok) throw(Exception(PROJECTFILE_CORRUPTED));\r
+\r
+      QStringList dimensionStr = currentBiGroup.attribute("dimension","none").split(",");\r
+      if(dimensionStr.length() != 2) throw(Exception(PROJECTFILE_CORRUPTED));\r
+      int dimX = dimensionStr.at(0).toInt(&ok);\r
+      if(!ok) throw(Exception(PROJECTFILE_CORRUPTED));\r
+      int dimY = dimensionStr.at(1).toInt(&ok);\r
+      if(!ok) throw(Exception(PROJECTFILE_CORRUPTED));\r
+\r
+\r
+      GroupItem *insideGroup = searchGroupItemById(idGroup, topScene);\r
+      if(insideGroup == NULL) cout << "group null" << endl;\r
+      BlockItem *blockItem = new BlockItem(insideGroup->getRefBlock(), dispatcher, this);\r
+      blockItem->setChildGroupItem(insideGroup);\r
+      blockItem->setId(id);\r
+      blockItem->setPos(posX,posY);\r
+      blockItem->setDimension(dimX,dimY);\r
+\r
+      ((GroupItem*)currentScene->getGroupItem())->addBlockItem(blockItem);\r
+      currentScene->addItem(blockItem);\r
+      currentScene->addBlockItem(blockItem);\r
+\r
+      QDomNodeList interfaceNodes = currentBiGroup.elementsByTagName("big_iface");\r
+\r
+      for(int k=0; k<interfaceNodes.length(); k++){\r
+        QDomElement currentInterfaceNode = interfaceNodes.at(k).toElement();\r
+\r
+        int id = currentInterfaceNode.attribute("id","none").toInt(&ok);\r
+        if(!ok) throw(Exception(PROJECTFILE_CORRUPTED));\r
+\r
+        QString refName = currentInterfaceNode.attribute("ref_name","none");\r
+        if(refName == "none") throw(Exception(PROJECTFILE_CORRUPTED));\r
+\r
+        QString orientationStr = currentInterfaceNode.attribute("orientation","none");\r
+        int orientation = InterfaceItem::getIntOrientation(orientationStr);\r
+        if(orientation == -1) throw(Exception(PROJECTFILE_CORRUPTED));\r
+\r
+        double position = currentInterfaceNode.attribute("position","none").toDouble(&ok);\r
+        if(!ok) throw(Exception(PROJECTFILE_CORRUPTED));\r
+\r
+        GroupInterface *refInter = (GroupInterface*)insideGroup->searchInterfaceByName(refName)->refInter;\r
+        InterfaceItem *ifaceItem = new InterfaceItem(position, orientation, refInter, blockItem, this);\r
+        ifaceItem->setId(id);\r
+        blockItem->addInterface(ifaceItem);\r
+      }\r
+    }\r
+  }\r
+  cout << "blockItems \"group\" loaded and created succefully!" << endl;\r
+\r
+\r
+  for(int i=0; i<scenesNodes.length(); i++){\r
+    QDomElement currentSceneNode = scenesNodes.at(i).toElement();\r
+\r
+    QDomElement groupItemNode = currentSceneNode.firstChildElement("group_item");\r
+\r
+    int id = groupItemNode.attribute("id","none").toInt(&ok);\r
+    if(!ok) throw(Exception(PROJECTFILE_CORRUPTED));\r
+    int idUpperItem = groupItemNode.attribute("upper_item","none").toInt(&ok);\r
+    if(!ok) throw(Exception(PROJECTFILE_CORRUPTED));\r
+\r
+    BlockItem *currentItem = searchBlockItemById(id,topScene);\r
+    GroupItem *upperItem = searchGroupItemById(idUpperItem, topScene);\r
+\r
+    if(currentItem != NULL && upperItem != NULL){\r
+      currentItem->setUpperItem(upperItem);\r
+    }\r
+  }\r
+\r
+  QDomNodeList connectionNodes = root.elementsByTagName("connection");\r
+\r
+  for(int i=0; i<connectionNodes.length(); i++){\r
+    QDomElement currentConnectionNode = connectionNodes.at(i).toElement();\r
+\r
+    int from = currentConnectionNode.attribute("from","none").toInt(&ok);\r
+    if(!ok) throw(Exception(PROJECTFILE_CORRUPTED));\r
+\r
+    int to = currentConnectionNode.attribute("to","none").toInt(&ok);\r
+    if(!ok) throw(Exception(PROJECTFILE_CORRUPTED));\r
+\r
+\r
+    InterfaceItem *iface1 = searchInterfaceItemById(from,topScene);\r
+    InterfaceItem *iface2 = searchInterfaceItemById(to,topScene);\r
+\r
+    if(iface1 != NULL && iface2 != NULL){\r
+      dispatcher->connect(iface1,iface2);\r
+    } else {\r
+      cout << "interfaces not found, connect canceled!" << endl;\r
+    }\r
+  }\r
+\r
+#endif\r
+}\r
+\r
+void Parameters::loadBlastConfiguration(QString confFile) throw(Exception) {\r
+\r
+  try {\r
+    validateXmlFile("blastconfig.xml", "blastconfig.xsd",Configuration);\r
+  }\r
+  catch(Exception err) {\r
+    throw(err);\r
+  }\r
+\r
+  bool ok;\r
+  // opening configFile\r
+  QFile configFile(confFile);\r
+  // reading in into QDomDocument\r
+  QDomDocument document("configFile");\r
+\r
+  if (!configFile.open(QIODevice::ReadOnly)) {\r
+    throw(Exception(CONFIGFILE_NOACCESS));\r
+  }\r
+  if (!document.setContent(&configFile)) {\r
+    configFile.close();\r
+    throw(Exception(CONFIGFILE_NOACCESS));\r
+  }\r
+  configFile.close();\r
+\r
+  //Get the root element\r
+  QDomElement config = document.documentElement();\r
+\r
+  QDomElement eltCat = config.firstChildElement("categories");\r
+  try {\r
+    categoryTree = new BlockLibraryTree();\r
+    categoryTree->load(eltCat);\r
+  }\r
+  catch(Exception err) {\r
+    throw(err);\r
+  }\r
+\r
+  QDomElement eltReferences = eltCat.nextSiblingElement("references");\r
+  refLib = eltReferences.attribute("lib_file","none");\r
+  cout << "references lib : " << qPrintable(refLib)  << endl;\r
+  int nbPathes;\r
+  QString nbPathesStr;\r
+  nbPathesStr = eltReferences.attribute("nb","none");\r
+  nbPathes = nbPathesStr.toInt(&ok);\r
+  QDomNodeList listBlockDir = eltReferences.elementsByTagName("reference_lib");\r
+  if ((!ok) || (nbPathes != listBlockDir.size())) throw(Exception(CONFIGFILE_CORRUPTED));\r
+\r
+  for(int i=0;i<listBlockDir.size();i++) {\r
+    QDomNode nodeBlockDir = listBlockDir.at(i);\r
+    QDomElement eltBlockDir = nodeBlockDir.toElement();\r
+    if (eltBlockDir.isNull()) throw(Exception(CONFIGFILE_CORRUPTED));\r
+    QString path = eltBlockDir.attribute("path","none");\r
+    if (path == "none") throw(Exception(CONFIGFILE_CORRUPTED));\r
+    refPathes.append(path);\r
+    cout << "references path : " << qPrintable(path) << endl;\r
+  }\r
+\r
+  QDomElement eltImpl = eltReferences.nextSiblingElement("implementations");\r
+  implLib = eltImpl.attribute("lib_file","none");\r
+  cout << "implementation lib : " << qPrintable(implLib)  << endl;\r
+  nbPathesStr = eltImpl.attribute("nb","none");\r
+  nbPathes = nbPathesStr.toInt(&ok);\r
+  QDomNodeList listImplDir = eltImpl.elementsByTagName("impl_lib");\r
+  if ((!ok) || (nbPathes != listImplDir.size())) throw(Exception(CONFIGFILE_CORRUPTED));\r
+\r
+  for(int i=0;i<listImplDir.size();i++) {\r
+    QDomNode nodeImplDir = listImplDir.at(i);\r
+    QDomElement eltImplDir = nodeImplDir.toElement();\r
+    if (eltImplDir.isNull()) throw(Exception(CONFIGFILE_CORRUPTED));\r
+    QString path = eltImplDir.attribute("path","none");\r
+    if (path == "none") throw(Exception(CONFIGFILE_CORRUPTED));\r
+    implPathes.append(path);\r
+    cout << "impl path : " << qPrintable(path) << endl << endl;\r
+  }\r
+  // getting elt = the element <defaults>\r
+  // for each child element, initialize the associated attributes of Parameters\r
+\r
+  QDomElement eltDefaults = eltImpl.nextSiblingElement("defaults");\r
+\r
+  QDomElement eltBlocks = eltDefaults.firstChildElement("blocks");\r
+  QString attributeStr = eltBlocks.attribute("width", "none");\r
+  defaultBlockWidth = attributeStr.toInt(&ok);\r
+  if (!ok || defaultBlockWidth < 1) throw(Exception(CONFIGFILE_CORRUPTED));\r
+  attributeStr = eltBlocks.attribute("height", "none");\r
+  defaultBlockHeight = attributeStr.toInt(&ok);\r
+  if (!ok || defaultBlockHeight < 1) throw(Exception(CONFIGFILE_CORRUPTED));\r
+  attributeStr = eltBlocks.attribute("font_size", "none");\r
+  defaultBlockFontSize = attributeStr.toFloat(&ok);\r
+  if (!ok || defaultBlockFontSize < 1) throw(Exception(CONFIGFILE_CORRUPTED));\r
+  attributeStr = eltBlocks.attribute("font", "none");\r
+  if (attributeStr == "none") throw(Exception(CONFIGFILE_CORRUPTED));\r
+  defaultBlockFontName = attributeStr;\r
+  defaultBlockFont = QFont(defaultBlockFontName, defaultBlockFontSize);\r
+\r
+  QDomElement eltInterfaces = eltBlocks.nextSiblingElement("interfaces");\r
+  attributeStr = eltInterfaces.attribute("width", "none");\r
+  arrowWidth = attributeStr.toInt(&ok);\r
+  if (!ok || arrowWidth < 1) throw(Exception(CONFIGFILE_CORRUPTED));\r
+  attributeStr = eltInterfaces.attribute("height", "none");\r
+  arrowHeight = attributeStr.toInt(&ok);\r
+  if (!ok || arrowHeight < 1) throw(Exception(CONFIGFILE_CORRUPTED));\r
+  attributeStr = eltInterfaces.attribute("linelength", "none");\r
+  arrowLineLength = attributeStr.toInt(&ok);\r
+  if (!ok || arrowLineLength < 1) throw(Exception(CONFIGFILE_CORRUPTED));\r
+  attributeStr = eltInterfaces.attribute("font_size", "none");\r
+  defaultIfaceFontSize = attributeStr.toFloat(&ok);\r
+  if (!ok || defaultIfaceFontSize < 1) throw(Exception(CONFIGFILE_CORRUPTED));\r
+  attributeStr = eltInterfaces.attribute("font", "none");\r
+  if (attributeStr == "none") throw(Exception(CONFIGFILE_CORRUPTED));\r
+  defaultIfaceFontName = attributeStr;\r
+  defaultIfaceFont = QFont(defaultIfaceFontName, defaultIfaceFontSize);\r
+\r
+  QDomElement eltConnections = eltInterfaces.nextSiblingElement("connections");\r
+  attributeStr = eltConnections.attribute("gaplength", "none");\r
+  connGapLength = attributeStr.toInt(&ok);\r
+  if (!ok || connGapLength < 1) throw(Exception(CONFIGFILE_CORRUPTED));\r
+}\r
+\r
+void Parameters::loadReferencesFromXml() throw(Exception) {\r
+  cout << "load references from xml" << endl;\r
+  for(int i=0;i<refPathes.size();i++) {\r
+    cout << "analyzing " << qPrintable(refPathes.at(i)) << endl;\r
+    QDir dir(refPathes.at(i));\r
+    QStringList filter;\r
+    filter << "*.xml";\r
+    dir.setNameFilters(filter);\r
+    QStringList list = dir.entryList();\r
+    for(int j=0;j<list.size();j++) {\r
+      QString fileName = dir.absolutePath();\r
+      fileName.append("/"+list.at(j));\r
+\r
+      QFile blockXML(fileName);\r
+      if (!blockXML.open(QIODevice::ReadOnly)) {\r
+        throw(Exception(BLOCKFILE_NOACCESS));\r
+      }\r
+      QTextStream in(&blockXML);\r
+      QString line = in.readLine();\r
+      line = in.readLine();\r
+\r
+      if (!line.contains("<block>")) {\r
+        blockXML.close();\r
+        continue;\r
+      }\r
+\r
+      blockXML.close();\r
+      try {\r
+        validateXmlFile(fileName,"block.xsd",Reference);\r
+      }\r
+      catch(Exception err) {\r
+        throw(err);\r
+      }\r
+\r
+      // reading in into QDomDocument\r
+      QDomDocument document ("FileXML");\r
+      if (!blockXML.open(QIODevice::ReadOnly)) {\r
+        throw(Exception(BLOCKFILE_NOACCESS));\r
+      }\r
+      if (!document.setContent(&blockXML)) {\r
+        blockXML.close();\r
+        throw(Exception(BLOCKFILE_NOACCESS));\r
+      }\r
+      blockXML.close();\r
+\r
+      QDomElement blockRoot = document.documentElement();\r
+      QString name = blockRoot.tagName();\r
+      if (name == "block") {\r
+\r
+        cout << "xml:" << fileName.toStdString() << endl;\r
+        ReferenceBlock* b = new ReferenceBlock(fileName);\r
+        try {\r
+          b->load(blockRoot);\r
+          b->setHashMd5();\r
+        }\r
+        catch(int err) {\r
+          throw(err);\r
+        }\r
+        cout << "xml:" << b->getXmlFile().toStdString() << endl;\r
+\r
+        availableBlocks.append(b);\r
+        foreach (int id,b->getCategories()) {\r
+          cout << "ajout du bloc dans cat n° : " << id << endl;\r
+          BlockCategory* cat = categoryTree->searchCategory(id);\r
+          cat->blocks.append(b);\r
+        }\r
+      }\r
+    }\r
+  }\r
+}\r
+\r
+void Parameters::loadReferencesFromLib() throw(Exception) {\r
+\r
+  cout << "loading references from lib" << endl;\r
+\r
+  // removing blocks from category tree if they exist\r
+  categoryTree->clearBlocks();\r
+  // deleting existings blocks\r
+  ReferenceBlock* b = NULL;\r
+  for(int i=0;i<availableBlocks.size();i++) {\r
+    b = availableBlocks.at(i);\r
+    delete b;\r
+  }\r
+  availableBlocks.clear();\r
+\r
+  QFile libFile(refLib);\r
+  if (!libFile.open(QIODevice::ReadOnly)) {\r
+    throw(Exception(BLOCKFILE_NOACCESS));\r
+  }\r
+  QDataStream in(&libFile);\r
+  quint32 size;\r
+\r
+  in >> size;\r
+\r
+  int nbBlocks;\r
+  in >> nbBlocks;\r
+  for(int i=0;i<nbBlocks;i++) {\r
+    b = new ReferenceBlock("");\r
+    in >> *b;\r
+    availableBlocks.append(b);\r
+    foreach (int id,b->getCategories()) {\r
+      BlockCategory* cat = categoryTree->searchCategory(id);\r
+      cat->blocks.append(b);\r
+    }\r
+  }\r
+  libFile.close();\r
+}\r
+\r
+void Parameters::saveReferencesToLib() throw(Exception) {\r
+\r
+  cout << "saving blocks in " << qPrintable(refLib) << endl;\r
+  QFile libFile(refLib);\r
+  if (!libFile.open(QIODevice::WriteOnly)) {\r
+    throw(Exception(BLOCKFILE_NOACCESS));\r
+  }\r
+  QDataStream out(&libFile);\r
+\r
+  out.setVersion(QDataStream::Qt_5_0);\r
+\r
+  QByteArray blockData;\r
+  QDataStream toWrite(&blockData, QIODevice::WriteOnly);\r
+\r
+  toWrite << availableBlocks.size();\r
+  for(int i=0;i<availableBlocks.size();i++) {\r
+    ReferenceBlock* b = availableBlocks.at(i);\r
+    toWrite << *b;\r
+  }\r
+\r
+  out << blockData;\r
+\r
+  libFile.close();\r
+\r
+}\r
+\r
+void Parameters::loadImplementationsFromXml() throw(Exception) {\r
+\r
+  for(int i=0;i<implPathes.size();i++) {\r
+    cout << "analyzing " << qPrintable(implPathes.at(i)) << endl;\r
+    QDir dir(implPathes.at(i));\r
+    QStringList filter;\r
+    filter << "*.xml";\r
+    dir.setNameFilters(filter);\r
+    QStringList list = dir.entryList();\r
+    for(int j=0;j<list.size();j++) {\r
+      QString fileName = dir.absolutePath();\r
+      fileName.append("/"+list.at(j));\r
+\r
+      cout << "checking " << qPrintable(fileName) << " is an implementation file ...";\r
+      QFile implXML(fileName);\r
+      if (!implXML.open(QIODevice::ReadOnly)) {\r
+        throw(Exception(IMPLFILE_NOACCESS));\r
+      }\r
+      QTextStream in(&implXML);\r
+      QString line = in.readLine();\r
+      line = in.readLine();\r
+\r
+      if (!line.contains("<block_impl")) {\r
+        implXML.close();\r
+        continue;\r
+      }\r
+\r
+      implXML.close();\r
+      cout << "OK" << endl;\r
+      cout << "reading " << qPrintable(fileName) << " content ...";\r
+      /*\r
+      try {\r
+        validateXmlFile(fileName,"block.xsd",Implementation);\r
+      }\r
+      catch(Exception e) {\r
+        throw(e);\r
+      }\r
+      */\r
+      // reading in into QDomDocument\r
+      QDomDocument document ("FileXML");\r
+      if (!implXML.open(QIODevice::ReadOnly)) {\r
+        throw(Exception(IMPLFILE_NOACCESS));\r
+      }\r
+      cout << "OK" << endl;\r
+      cout << "convert " << qPrintable(fileName) << " content into document...";\r
+      if (!document.setContent(&implXML)) {\r
+        implXML.close();\r
+        throw(Exception(IMPLFILE_NOACCESS));\r
+      }\r
+      implXML.close();\r
+\r
+      QDomElement implRoot = document.documentElement();\r
+      QString refXml = implRoot.attribute("ref_name","none");\r
+      QString refMd5 = implRoot.attribute("ref_md5","none");\r
+      BlockImplementation* impl = new BlockImplementation(fileName,refXml,refMd5);\r
+      availableImplementations.append(impl);\r
+\r
+      ReferenceBlock* ref = NULL;\r
+      if (! refMd5.isEmpty()) {\r
+        ref = searchBlockByMd5(refMd5);\r
+      }\r
+      if (ref == NULL) {\r
+        ref = searchBlockByXml(refXml);\r
+      }\r
+      if (ref == NULL) {\r
+        cout << "Cannot find a reference block for impl :" << qPrintable(fileName) << endl;\r
+      }\r
+      ref->addImplementation(impl);\r
+      impl->setReference(ref);\r
+      cout << "OK" << endl;\r
+    }\r
+  }\r
+}\r
+\r
+void Parameters::loadImplementationsFromLib() throw(Exception) {\r
+\r
+  cout << "loading implementations from lib" << endl;\r
+\r
+  BlockImplementation* impl = NULL;\r
+  ReferenceBlock* ref = NULL;\r
+  for(int i=0;i<availableImplementations.size();i++) {\r
+    impl = availableImplementations.at(i);\r
+    delete impl;\r
+  }\r
+  availableImplementations.clear();\r
+\r
+  QFile libFile(implLib);\r
+  if (!libFile.open(QIODevice::ReadOnly)) {\r
+    throw(Exception(IMPLFILE_NOACCESS));\r
+  }\r
+  QDataStream in(&libFile);\r
+  quint32 size;\r
+\r
+  in >> size;\r
+\r
+  int nbImpls;\r
+  in >> nbImpls;\r
+  for(int i=0;i<nbImpls;i++) {\r
+    impl = new BlockImplementation("");\r
+    in >> *impl;\r
+    availableImplementations.append(impl);\r
+    QString refMd5 = impl->getReferenceMd5();\r
+    QString refXml = impl->getReferenceXml();\r
+    ref = NULL;\r
+    if (! refMd5.isEmpty()) {\r
+      ref = searchBlockByMd5(refMd5);\r
+    }\r
+    if (ref == NULL) {\r
+      ref = searchBlockByXml(refXml);\r
+    }\r
+    if (ref == NULL) {\r
+      cout << "Cannot find a reference block for impl :" << qPrintable(impl->getXmlFile()) << endl;\r
+    }\r
+    ref->addImplementation(impl);\r
+    impl->setReference(ref);\r
+  }\r
+  libFile.close();\r
+}\r
+\r
+void Parameters::saveImplementationsToLib() throw(Exception) {\r
+\r
+  cout << "saving implementations in " << qPrintable(implLib) << endl;\r
+  QFile libFile(implLib);\r
+  if (!libFile.open(QIODevice::WriteOnly)) {\r
+    throw(Exception(IMPLFILE_NOACCESS));\r
+  }\r
+  QDataStream out(&libFile);\r
+\r
+  out.setVersion(QDataStream::Qt_5_0);\r
+\r
+  QByteArray blockData;\r
+  QDataStream toWrite(&blockData, QIODevice::WriteOnly);\r
+\r
+  toWrite << availableImplementations.size();\r
+  for(int i=0;i<availableImplementations.size();i++) {\r
+    BlockImplementation* impl = availableImplementations.at(i);\r
+    toWrite << *impl;\r
+  }\r
+\r
+  out << blockData;\r
+\r
+  libFile.close();\r
+\r
+}\r
+void Parameters::addAvailableBlock(ReferenceBlock *block) {\r
+  availableBlocks.append(block);\r
+  foreach (int id,block->getCategories()) {\r
+    cout << "ajout du bloc dans cat n° : " << id << endl;\r
+    BlockCategory* cat = categoryTree->searchCategory(id);\r
+    cat->blocks.append(block);\r
+  }\r
+}\r
+\r
+void Parameters::parametersValidation() {\r
+  QList<AbstractBlock*> blocksToConfigure = getBlocksToConfigure();\r
+\r
+  if(!blocksToConfigure.isEmpty()){\r
+    BlocksToConfigureWidget *widget = new BlocksToConfigureWidget(blocksToConfigure, this, NULL);\r
+    widget->show();\r
+  }\r
+}\r
+\r
+void Parameters::connectionsValidation() {\r
+\r
+#ifdef DEBUG_INCLFUN\r
+\r
+  QStack<AbstractInterface*> *interfaceToValidate = new QStack<AbstractInterface*>;\r
+  QList<AbstractInterface*> *validatedInterface = new QList<AbstractInterface*>;\r
+\r
+  foreach(AbstractInterface *inter, topWindow->getScene()->getGroupItem()->getRefBlock()->getInterfaces()){\r
+    foreach(AbstractInterface *connectedInter, inter->getConnectedTo()){\r
+\r
+      inter->setWidth(connectedInter->getWidth());\r
+      interfaceToValidate->push(connectedInter);\r
+    }\r
+  }\r
+\r
+\r
+  try{\r
+    while(!interfaceToValidate->isEmpty()){\r
+      interfaceToValidate->pop()->connectionsValidation(interfaceToValidate, validatedInterface);\r
+    }\r
+  }\r
+  catch(Exception e){\r
+    cerr << e.getMessage().toStdString() << endl;\r
+  }\r
+#endif\r
+}\r
+\r
+QList<AbstractBlock *> Parameters::getBlocksToConfigure() {\r
+\r
+#ifdef DEBUG_INCLFUN\r
+\r
+  QList<AbstractBlock*> *checkedBlocks = new QList<AbstractBlock*>;\r
+  QList<AbstractBlock*> *blocksToConfigure = new QList<AbstractBlock*>;\r
+\r
+  foreach(AbstractInterface *inter, topWindow->getScene()->getGroupItem()->getRefBlock()->getInterfaces()){\r
+    foreach(AbstractInterface *connectedInter, inter->getConnectedTo()){\r
+      if(!checkedBlocks->contains(connectedInter->getOwner())){\r
+        connectedInter->getOwner()->parametersValidation(checkedBlocks, blocksToConfigure);\r
+      }\r
+    }\r
+  }\r
+  return *blocksToConfigure;\r
+#endif\r
+}\r
+\r
+\r
+void Parameters::updateToolbar() {\r
+  int nb = currentScene->getBlockItems().length();\r
+  for(int i = 0; i<nb; i++){\r
+    if(currentScene->getBlockItems().at(i)->isSelected()){\r
+      currentScene->getGroupWindow()->enableGroupButton(true);\r
+      return;\r
+    }\r
+  }\r
+  currentScene->getGroupWindow()->enableGroupButton(false);\r
+}\r
+\r
+\r
+void Parameters::updateIds() {\r
+\r
+  /* a in-width cross of the graph must be done so that ids of GroupItem\r
+     are in the correct ordre when saving/loading a project\r
+   */\r
+  int countItem = 1;\r
+  int countIface = 1;\r
+  QList<GroupScene *> fifo;\r
+  fifo.append(topScene);\r
+  while (!fifo.isEmpty()) {\r
+    GroupScene* scene = fifo.takeFirst();\r
+    countItem = scene->setItemsId(countItem);\r
+    countIface = scene->setInterfacesId(countIface);\r
+    foreach(GroupScene* s, scene->getChildrenScene()) {\r
+      fifo.append(s);\r
+    }\r
+  }\r
+}\r
+\r
+\r
+ReferenceBlock *Parameters::searchBlockByXml(QString xmlName) {\r
+  foreach(ReferenceBlock *block, availableBlocks){\r
+    if(block->getXmlFile().contains(xmlName))\r
+      return block;\r
+  }\r
+  return NULL;\r
+}\r
+\r
+ReferenceBlock *Parameters::searchBlockByMd5(QString sumMd5) {\r
+  foreach(ReferenceBlock *block, availableBlocks){\r
+    if(block->getHashMd5() == sumMd5)\r
+      return block;\r
+  }\r
+  return NULL;\r
+}\r
+\r
+void Parameters::save(QString confFile) {\r
+\r
+//#ifdef DEBUG_INCLFUN\r
+\r
+  updateIds();\r
+  QList<ConnectionItem*> allConnections;\r
+  QFile file(confFile);\r
+  if(file.open(QIODevice::WriteOnly)){\r
+\r
+    QXmlStreamWriter writer(&file);\r
+\r
+    writer.setAutoFormatting(true);\r
+    writer.writeStartDocument();\r
+\r
+    writer.writeStartElement("blast_project");\r
+    writer.writeStartElement("scenes");\r
+\r
+    writer.writeAttribute("count",QString::number(dispatcher->getNumberOfScenes()));\r
+\r
+    // cross the scene level by level using a FIFO\r
+    QList<GroupScene*> fifoScene;\r
+    fifoScene.append(topScene);\r
+    foreach(ConnectionItem* item, topScene->getConnectionItems()) {\r
+      allConnections.append(item);\r
+    }\r
+\r
+    GroupScene *scene;\r
+    while (!fifoScene.isEmpty()) {\r
+      scene = fifoScene.takeFirst();\r
+      scene->save(writer);\r
+      foreach(GroupScene* s, scene->getChildrenScene()) {\r
+        fifoScene.append(s);\r
+      }\r
+      foreach(ConnectionItem* item, topScene->getConnectionItems()) {\r
+        allConnections.append(item);\r
+      }\r
+    }\r
+\r
+\r
+    writer.writeStartElement("connections");\r
+    foreach(ConnectionItem* item, allConnections) {\r
+\r
+      writer.writeStartElement("connection");\r
+\r
+      writer.writeAttribute("from",QString::number(item->getFromInterfaceItem()->getId()));\r
+      writer.writeAttribute("to", QString::number(item->getToInterfaceItem()->getId()));\r
+\r
+      writer.writeEndElement();\r
+    }\r
+\r
+    writer.writeEndElement();    //</connections>\r
+    writer.writeEndElement();      //</blast_project\r
+\r
+    writer.writeEndDocument();\r
+\r
+    file.close();\r
+    unsaveModif = false;\r
+  }\r
+//#endif\r
+}\r
+\r
+void Parameters::setArrowPathes() {\r
+  QPainterPath _inArrow;\r
+  _inArrow.lineTo(arrowLineLength,0);\r
+  _inArrow.lineTo(arrowLineLength+arrowWidth,-arrowHeight/2);\r
+  _inArrow.lineTo(arrowLineLength+arrowWidth,arrowHeight/2);\r
+  _inArrow.lineTo(arrowLineLength,0);\r
+  _inArrow.closeSubpath();\r
+  inArrow = _inArrow;\r
+\r
+  QPainterPath _outArrow;\r
+  _outArrow.lineTo(arrowLineLength,0);\r
+  _outArrow.lineTo(arrowLineLength,-arrowHeight/2);\r
+  _outArrow.lineTo(arrowLineLength+arrowWidth,0);\r
+  _outArrow.lineTo(arrowLineLength,arrowHeight/2);\r
+  _outArrow.lineTo(arrowLineLength,0);\r
+  _outArrow.closeSubpath();\r
+  outArrow = _outArrow;\r
+\r
+}\r
+\r
+GroupScene* Parameters::searchSceneById(int id, GroupScene *scene) {\r
+\r
+  if (scene->getId() == id) return scene;\r
+  GroupScene* sc = NULL;\r
+\r
+  foreach(GroupScene *s, scene->getChildrenScene()) {\r
+    sc = searchSceneById(id,s);\r
+    if (sc != NULL) return sc;\r
+  }\r
+  return NULL;\r
+}\r
+\r
+GroupItem* Parameters::searchGroupItemById(int id, GroupScene *scene) {\r
+\r
+  if (scene->getGroupItem()->getId() == id) return scene->getGroupItem();\r
+\r
+  GroupItem* item = NULL;\r
+  foreach(GroupScene *s, scene->getChildrenScene()) {\r
+    item = searchGroupItemById(id,s);\r
+    if (item != NULL) return item;\r
+  }\r
+  return NULL;\r
+}\r
+\r
+BoxItem* Parameters::searchBlockItemById(int id, GroupScene *scene) {\r
+\r
+  foreach(BoxItem *item, scene->getBlockItems()){\r
+    if(item->getId() == id){\r
+      return item;\r
+    }\r
+  }\r
+\r
+  BoxItem* item = NULL;\r
+  foreach(GroupScene *s, scene->getChildrenScene()) {\r
+    item = searchBlockItemById(id,s);\r
+    if (item != NULL) return item;\r
+  }\r
+  return NULL;\r
+}\r
+\r
+InterfaceItem* Parameters::searchInterfaceItemById(int id, GroupScene* scene) {\r
+\r
+  foreach(InterfaceItem *item, scene->getGroupItem()->getInterfaces()){\r
+    if(item->getId() == id){\r
+      return item;\r
+    }\r
+  }\r
+  foreach(BoxItem *block, scene->getBlockItems()){\r
+    foreach(InterfaceItem *item, block->getInterfaces()){\r
+      if(item->getId() == id){\r
+        return item;\r
+      }\r
+    }\r
+  }\r
+  InterfaceItem* item = NULL;\r
+  foreach(GroupScene *s, scene->getChildrenScene()) {\r
+    item = searchInterfaceItemById(id,s);\r
+    if (item != NULL) return item;\r
+  }\r
+  return NULL;\r
+}\r
diff --git a/Parameters.h b/Parameters.h
new file mode 100644 (file)
index 0000000..8393a79
--- /dev/null
@@ -0,0 +1,171 @@
+#ifndef __PARAMETERS_H__\r
+#define __PARAMETERS_H__\r
+\r
+#include <iostream>\r
+\r
+#include <QtCore>\r
+#include <QtGui>\r
+#include <QtWidgets>\r
+#include <QtXml>\r
+#include <QtXmlPatterns>\r
+\r
+class Dispatcher;\r
+class BlockLibraryTree;\r
+class AbstractBlock;\r
+class ReferenceBlock;\r
+class GroupBlock;\r
+class FunctionalBlock;\r
+class GroupScene;\r
+class GroupItem;\r
+class BoxItem;\r
+class InterfaceItem;\r
+class Graph;\r
+\r
+#include "BlockImplementation.h"\r
+\r
+#include "Exception.h"\r
+class Exception;\r
+\r
+// defines for current mode\r
+#define MODE_EDITION 1\r
+#define MODE_ADDBLOC 2\r
+#define MODE_ADDCONN 3\r
+\r
+\r
+using namespace std;\r
+using namespace Qt;\r
+\r
+class Parameters {\r
+\r
+public :\r
+\r
+  enum Direction { NoDirection, East, North, West, South};\r
+\r
+  /* state of cursorn:\r
+     - CursorInBlock: cursor is within the main box of a block/group item\r
+     - CursorOnBlockBorder: cursor is on a block/group item border\r
+     - CursorOnInterface: cursor is on a block/group item Interface\r
+     - CursorOnConnection: cursor is one a connection\r
+     - CursorNowhere: none of the previous cases\r
+  */\r
+  enum CursorState { CursorNowhere = 0, CursorInBlock, CursorInGroupTitle, CursorOnBorder, CursorOnInterface, CursorOnConnection };\r
+  /* state of edition:\r
+\r
+   */\r
+  enum EditState { EditNoOperation = 0, EditBlockMove, EditBlockResize, EditGroupMove, EditGroupResize, EditInterfaceMove, EditInterfaceDeselect, EditConnectionResize, EditStartConnection, EditCloseConnection, EditAbortConnection};\r
+\r
+  enum XmlFileType { Configuration = 1, Reference, Implementation, Project };\r
+  Parameters();\r
+  ~Parameters();\r
+\r
+  // getter\r
+  inline GroupScene* getCurrentScene() { return currentScene; }\r
+  inline GroupScene* getTopScene() { return topScene; }\r
+\r
+  // setter\r
+  inline void setTopScene(GroupScene* _topScene) { topScene = _topScene; }\r
+  inline void setCurrentScene(GroupScene* _currentScene) { currentScene = _currentScene; }\r
+  inline void setEditState(EditState state) { editState = state; }\r
+  inline void setCursorState(CursorState state) { cursorState = state; }\r
+  inline void setDispatcher(Dispatcher* _dispatcher) { dispatcher = _dispatcher;}\r
+\r
+  /***************************************************\r
+    attributes that are general to the application\r
+  ***************************************************/  \r
+  BlockLibraryTree* categoryTree;\r
+  QList<QString> refPathes;\r
+  QList<QString> implPathes;\r
+  QList<ReferenceBlock*> availableBlocks;\r
+  QList<BlockImplementation*> availableImplementations;\r
+\r
+\r
+  QString refLib;\r
+  QString implLib;\r
+\r
+  // defaults for vhdl\r
+  int wbDataWidth;\r
+  int wbAddressWidth;\r
+  // defaults for scene elements\r
+  int defaultBlockWidth;\r
+  int defaultBlockHeight;\r
+  QFont defaultBlockFont;\r
+  QString defaultBlockFontName;\r
+  int defaultBlockFontSize;\r
+  int arrowWidth;\r
+  int arrowHeight;\r
+  int arrowLineLength;\r
+  QFont defaultIfaceFont;\r
+  QString defaultIfaceFontName;\r
+  int defaultIfaceFontSize;\r
+  int connGapLength;\r
+  QPainterPath inArrow;\r
+  QPainterPath outArrow;\r
+\r
+  /***************************************************\r
+   attributes that are specific for the current project\r
+  ****************************************************/\r
+  int sceneMode; // takes values from MODE_XXX\r
+  CursorState cursorState;\r
+  EditState editState; // takes values from EDIT_STATE_XXX\r
+  bool unsaveModif;\r
+  bool isRstClkShown;\r
+\r
+  Graph* createGraph();\r
+  void destroyGraph();\r
+  inline Graph* getGraph() { return graph; }\r
+  GroupBlock* addGroupBlock(); // adding an empty GroupBlock to the current group\r
+  FunctionalBlock* addFunctionalBlock(int idCategory, int idBlock); // adding a functional block to current group\r
+  FunctionalBlock* duplicateFunctionalBlock(FunctionalBlock* block); // adding a copy of a functional block to current group\r
+\r
+\r
+  void clear();\r
+\r
+  QDomElement openProjectFile(const QString& projectFileName) throw(Exception);\r
+  void loadProject(QDomElement root);\r
+\r
+  void loadBlastConfiguration(QString confFile) throw(Exception);\r
+  void loadReferencesFromXml() throw(Exception);\r
+  void loadReferencesFromLib() throw(Exception);\r
+  void saveReferencesToLib() throw(Exception);\r
+\r
+  void loadImplementationsFromXml() throw(Exception);\r
+  void loadImplementationsFromLib() throw(Exception);\r
+  void saveImplementationsToLib() throw(Exception);\r
+\r
+  void addAvailableBlock(ReferenceBlock *block);  \r
+  void parametersValidation();\r
+  void connectionsValidation();\r
+  QList<AbstractBlock *> getBlocksToConfigure();\r
+\r
+  void updateToolbar();\r
+\r
+\r
+  ReferenceBlock* searchBlockByXml(QString xmlName);\r
+  ReferenceBlock* searchBlockByMd5(QString sumMd5);\r
+\r
+  void save(QString confFile);\r
+\r
+\r
+  QString projectPath;\r
+\r
+private:\r
+  Graph* graph; // the graph model of blocks\r
+  Dispatcher* dispatcher;\r
+  GroupScene* topScene;\r
+  GroupScene* currentScene;\r
+\r
+  void setArrowPathes();  \r
+  void updateIds();\r
+\r
+  GroupScene* searchSceneById(int id, GroupScene* scene);\r
+  BoxItem* searchBlockItemById(int id, GroupScene* scene);\r
+  GroupItem* searchGroupItemById(int id, GroupScene* scene);\r
+  InterfaceItem* searchInterfaceItemById(int id, GroupScene *scene);\r
+\r
+  void validateXmlFile(const QString& xmlFileName, const QString& xsdFileName, XmlFileType fileType) throw(Exception);\r
+  bool validate(QFile& fileXml, QFile& fileSchema);\r
+\r
+};\r
+\r
+\r
+#endif // __PARAMETERS_H__\r
diff --git a/ParametersWindow.cpp b/ParametersWindow.cpp
new file mode 100644 (file)
index 0000000..07f96fa
--- /dev/null
@@ -0,0 +1,72 @@
+#include "ParametersWindow.h"
+#include "Parameters.h"
+#include "BlocksToConfigureWidget.h"
+#include "BlockParameter.h"
+#include "AbstractBlock.h"
+
+ParametersWindow::ParametersWindow(AbstractBlock *_block, Parameters *_params, BlocksToConfigureWidget *btcw, QWidget *parent) :
+    QWidget(parent)
+{
+    block = _block;
+    confWidget = btcw;
+    params = _params;
+
+    layout = new QGridLayout;
+
+    name = new QLabel;
+    value = new QLineEdit;
+    context = new QLabel;
+    type = new QLabel;
+
+    comboBox = new QComboBox;
+
+    foreach(BlockParameter *param, block->getParameters()){
+      comboBox->addItem(param->getName());
+    }
+    connect(comboBox, SIGNAL(currentIndexChanged(int)), this, SLOT(updateData()));
+    updateData();
+
+    saveButton = new QPushButton("Save");
+    connect(saveButton, SIGNAL(clicked()), this, SLOT(save()));
+
+    layout->addWidget(new QLabel("Parameters"), 0, 0);
+    layout->addWidget(comboBox, 0, 1);
+
+    layout->addWidget(new QLabel(" "), 1, 0);
+
+    layout->addWidget(new QLabel("Name"), 2, 0);
+    layout->addWidget(name, 2, 1);
+    layout->addWidget(new QLabel("Value"), 3, 0);
+    layout->addWidget(value, 3, 1);
+    layout->addWidget(new QLabel("Context"), 4, 0);
+    layout->addWidget(context, 4, 1);
+    layout->addWidget(new QLabel("Type"), 5, 0);
+    layout->addWidget(type, 5, 1);
+
+    layout->addWidget(saveButton, 6, 0);
+
+    this->setLayout(layout);
+
+    show();
+}
+
+void ParametersWindow::updateData()
+{
+  BlockParameter *param = block->getParameters().at(comboBox->currentIndex());
+  name->setText(param->getName());
+  value->setText(param->getValue().toString());
+  context->setText(param->getContext());
+  type->setText(param->getTypeString());
+}
+
+void ParametersWindow::save()
+{
+  BlockParameter *param = block->getParameters().at(comboBox->currentIndex());
+  param->setValue(value->text());  
+
+  //params->parametersValidation();
+  if(confWidget != NULL){
+    confWidget->updateBlocksList();
+  }
+  close();
+}
diff --git a/ParametersWindow.h b/ParametersWindow.h
new file mode 100644 (file)
index 0000000..df6e4fc
--- /dev/null
@@ -0,0 +1,34 @@
+#ifndef __PARAMETERSWINDOW_H__
+#define __PARAMETERSWINDOW_H__
+
+#include <QtWidgets>
+
+class Parameters;
+class AbstractBlock;
+class BlocksToConfigureWidget;
+
+class ParametersWindow : public QWidget {
+  Q_OBJECT
+
+public:
+    ParametersWindow(AbstractBlock *block, Parameters *_params, BlocksToConfigureWidget *btcw=NULL, QWidget *parent=0);
+
+private:
+    AbstractBlock *block;
+    Parameters *params;
+    BlocksToConfigureWidget *confWidget;
+    QGridLayout *layout;
+    QComboBox *comboBox;
+    QLabel *name;
+    QLabel *context;
+    QLineEdit *value;
+    QLabel *type;
+    QPushButton *saveButton;
+
+private slots:
+    void updateData();
+    void save();
+
+};
+
+#endif // PARAMETERSWINDOW_H
diff --git a/ReferenceBlock.cpp b/ReferenceBlock.cpp
new file mode 100644 (file)
index 0000000..8b50bfa
--- /dev/null
@@ -0,0 +1,471 @@
+#include "ReferenceBlock.h"
+
+#include "ReferenceInterface.h"
+#include "BlockParameter.h"
+#include "BlockParameterUser.h"
+#include "BlockParameterGeneric.h"
+#include "BlockParameterPort.h"
+#include "BlockParameterWishbone.h"
+
+ReferenceBlock::ReferenceBlock(const QString _xmlFile) : AbstractBlock() {
+  xmlFile = _xmlFile;
+}
+
+void ReferenceBlock::addCategory(int id) {
+ categories.append(id);
+}
+
+void ReferenceBlock::setBriefDescription(const QString& str) {
+  if(str != NULL)
+    descriptionBrief = str;
+}
+
+void ReferenceBlock::setDetailedDescription(const QString& str) {
+  if(str != NULL)
+    descriptionDetail = str;
+}
+
+void ReferenceBlock::addImplementation(BlockImplementation *impl) {
+  implementations.append(impl);
+}
+
+void ReferenceBlock::setHashMd5() {
+  QFile file(xmlFile);
+  if (file.open(QIODevice::ReadOnly)) {
+    QByteArray fileData = file.readAll();
+    QByteArray hashData = QCryptographicHash::hash(fileData, QCryptographicHash::Md5);
+    hashMd5 = QString(hashData.toHex());
+    cout << qPrintable(xmlFile) << " has md5 hash : " << qPrintable(hashMd5) << endl;
+  }
+  else {
+    hashMd5 = "";
+  }
+}
+
+void ReferenceBlock::load(QDomElement &elt) throw(Exception) {
+
+
+  cout << "Block : get informations" << endl;  
+  QDomElement eltInfo  = elt.firstChildElement("informations");
+  try {
+    loadInformations(eltInfo);
+  }
+  catch(int err) {
+    throw(err);
+  }
+
+  cout << "Block : get params" << endl;  
+  QDomElement eltParams  = eltInfo.nextSiblingElement("parameters");
+  try {
+    loadParameters(eltParams);
+  }
+  catch(int err) {
+    throw(err);
+  }
+
+  cout << "Block : get interfaces" << endl;  
+  QDomElement eltInter  = eltParams.nextSiblingElement("interfaces");
+  try {
+    loadInterfaces(eltInter);
+  }
+  catch(int err) {
+    throw(err);
+  }  
+}
+
+void ReferenceBlock::loadInformations(QDomElement &elt) throw(Exception) {
+
+  bool ok;
+  if ((elt.isNull()) || (elt.tagName() != "informations")) throw (Exception(BLOCKFILE_CORRUPTED));
+  // getting name
+  cout << "Block info : get name" << endl;
+  QDomNode nodeName = elt.firstChild();  
+  QDomNode nodeNameTxt = nodeName.firstChild();
+  if (nodeNameTxt.isNull()) {
+    name = "no_name";
+  }
+  else {
+    QDomText txtName = nodeNameTxt.toText();
+    name = txtName.data().trimmed();
+    cout<< "block name : " << qPrintable(name) << endl;
+  }
+
+  // getting categories
+  cout << "Block info : get categories" << endl;  
+  QDomElement eltCat = nodeName.nextSiblingElement("category");
+
+  QString idsStr = eltCat.attribute("ids","none");
+  if (idsStr == "none") throw (Exception(BLOCKFILE_CORRUPTED));
+  QStringList listCat = idsStr.split(",");
+  foreach(QString str, listCat)
+  {
+    int idCat = str.toInt(&ok);
+    categories.append(idCat);
+  }
+
+  // getting description
+  cout << "Block info : get description" << endl;  
+  QDomElement eltDesc = eltCat.nextSiblingElement("description");
+  // getting brief  
+  QDomElement eltBrief = eltDesc.firstChildElement("brief");
+  QDomNode nodeBriefTxt = eltBrief.firstChild();
+  if (nodeBriefTxt.isNull()) {
+    descriptionBrief = "no brief description";
+  }
+  else {
+    QDomText txtBrief = nodeBriefTxt.toText();
+    descriptionBrief = txtBrief.data().trimmed();
+    cout << "block brief desc : " << qPrintable(descriptionBrief) << endl;
+  }
+  // getting detailed  
+  QDomElement eltDetail = eltBrief.nextSiblingElement("detailed");
+  QDomNode nodeDetailTxt = eltDetail.firstChild();
+  if (nodeDetailTxt.isNull()) {
+    descriptionDetail = "no detailed description";
+  }
+  else {
+    QDomText txtDetail = nodeDetailTxt.toText();
+    descriptionDetail = txtDetail.data().trimmed();
+    cout << "block detail desc : " << qPrintable(descriptionDetail) << endl;
+  }
+}
+
+void ReferenceBlock::loadParameters(QDomElement &elt) throw(Exception) {
+
+  if ((elt.isNull()) || (elt.tagName() != "parameters")) throw (Exception(BLOCKFILE_CORRUPTED));
+
+  QDomNodeList listNodeParam = elt.elementsByTagName("parameter");
+  for(int i=0; i<listNodeParam.size(); i++) {
+    QDomNode node = listNodeParam.at(i);    
+    QDomElement elt = node.toElement();    
+    QString nameStr = elt.attribute("name","none");    
+    QString contextStr = elt.attribute("context","none");
+    QString typeStr = elt.attribute("type","none");
+    QString valueStr = elt.attribute("value","none");
+    BlockParameter *param = NULL;
+
+    if(valueStr == "none"){
+        if (contextStr == "generic") throw (Exception(BLOCKFILE_CORRUPTED)); // set is required for generics
+        valueStr = "";
+    }
+    if (contextStr == "user") {
+      param = new BlockParameterUser(this,nameStr,valueStr);
+    }
+    else if (contextStr == "generic") {
+      param = new BlockParameterGeneric(this,nameStr,typeStr,valueStr);
+    }
+    else if (contextStr == "wb") {
+      QString widthStr = elt.attribute("width","none");
+      QString wbStr = elt.attribute("wishbone","none");
+      int access = 0;
+      int duration = 0;
+      QString wbValue = "";
+      QStringList listWb = wbStr.split(",");
+
+      if (listWb.at(0) == "r") {
+        access = BlockParameter::Read;
+      }
+      else if (wbStr == "w") {
+        access = BlockParameter::Write;
+        bool ok;
+        wbValue = listWb.at(1).toInt(&ok);
+        if(!ok){
+            if(listWb.at(1) == "true" || listWb.at(1) == "false"){
+                wbValue = listWb.at(1);
+            } else {
+                wbValue = "data";
+            }
+        }
+        if(listWb.at(2) == "trigger") {
+            duration = BlockParameter::Trigger;
+        }
+        else if(listWb.at(2) == "perm") {
+            duration = BlockParameter::Permanent;
+        }
+      }
+      param = new BlockParameterWishbone(this,nameStr,typeStr,widthStr,valueStr,access,wbValue,duration);
+    }
+    else if (contextStr == "port") {
+      QString ifaceStr = elt.attribute("iface","none");
+      param = new BlockParameterPort(this,nameStr,valueStr,ifaceStr);
+
+    }
+    else {
+      throw (Exception(BLOCKFILE_CORRUPTED));
+    }
+    params.append(param);
+  }
+}
+
+void ReferenceBlock::loadInterfaces(QDomElement &elt) throw(Exception) {
+
+  QString nameStr;
+  QString typeStr;
+  QString widthStr;
+  QString purposeStr;
+  int purpose;
+  QString levelStr;
+  int level;
+  QString multStr;
+  int mult;
+  AbstractInterface* inter;
+
+  if ((elt.isNull()) || (elt.tagName() != "interfaces")) throw (Exception(BLOCKFILE_CORRUPTED));
+
+  QDomElement eltInputs = elt.firstChildElement("inputs");
+  QDomNodeList listNodeInputs = eltInputs.elementsByTagName("input");
+  for(int i=0;i<listNodeInputs.size();i++) {
+    QDomNode node = listNodeInputs.at(i);
+    QDomElement eltInput = node.toElement();
+    nameStr = eltInput.attribute("name","none");
+    typeStr = eltInput.attribute("type","none");
+    widthStr = eltInput.attribute("width","none");
+    purposeStr = eltInput.attribute("purpose","none");
+    cout << "block : " << this->getName().toStdString() << endl;
+    cout << "purpose for " << nameStr.toStdString() << " : " << purposeStr.toStdString() << endl;
+    purpose = ReferenceInterface::translatePurpose(purposeStr);
+    cout << "translated purpose : " << purpose << endl;
+    levelStr = eltInput.attribute("level","none");
+    level = ReferenceInterface::translateLevel(levelStr);
+    multStr = eltInput.attribute("multiplicity","none");
+    mult = ReferenceInterface::translateMultiplicity(multStr);
+
+    inter = new ReferenceInterface(this,nameStr,typeStr,widthStr,AbstractInterface::Input, purpose, level, mult);
+    inputs.append(inter);
+  }
+
+  QDomElement eltOutputs = eltInputs.nextSiblingElement("outputs");
+  QDomNodeList listNodeOutputs = eltOutputs.elementsByTagName("output");
+  for(int i=0;i<listNodeOutputs.size();i++) {
+    QDomNode node = listNodeOutputs.at(i);
+    QDomElement eltOutput = node.toElement();
+    nameStr = eltOutput.attribute("name","none");
+    typeStr = eltOutput.attribute("type","none");
+    widthStr = eltOutput.attribute("width","none");
+    purposeStr = eltOutput.attribute("type","none");
+    purpose = ReferenceInterface::translatePurpose(purposeStr);
+    levelStr = eltOutput.attribute("level","none");
+    level = ReferenceInterface::translateLevel(levelStr);
+    multStr = eltOutput.attribute("multiplicity","none");
+    mult = ReferenceInterface::translateMultiplicity(multStr);
+
+    inter = new ReferenceInterface(this,nameStr,typeStr,widthStr,AbstractInterface::Output, purpose, level, mult);
+    outputs.append(inter);
+  }
+
+  QDomElement eltBidirs = eltInputs.nextSiblingElement("bidirs");
+  QDomNodeList listNodeBidirs = eltBidirs.elementsByTagName("bidir");
+  for(int i=0;i<listNodeBidirs.size();i++) {
+    QDomNode node = listNodeBidirs.at(i);
+    QDomElement eltBidir = node.toElement();
+    nameStr = eltBidir.attribute("name","none");
+    typeStr = eltBidir.attribute("type","none");
+    widthStr = eltBidir.attribute("width","none");
+    purposeStr = eltBidir.attribute("type","none");
+    purpose = ReferenceInterface::translatePurpose(purposeStr);
+    levelStr = eltBidir.attribute("level","none");
+    level = ReferenceInterface::translateLevel(levelStr);
+    multStr = eltBidir.attribute("multiplicity","none");
+    mult = ReferenceInterface::translateMultiplicity(multStr);
+
+    inter = new ReferenceInterface(this,nameStr,typeStr,widthStr,AbstractInterface::InOut, purpose, level, mult);
+    bidirs.append(inter);
+  }
+}
+
+void ReferenceBlock::parametersValidation(QList<AbstractBlock *> *checkedBlocks, QList<AbstractBlock *> *blocksToConfigure)
+{
+    return;
+}
+
+/* operator<<() :
+   only used to save all ReferenceBlock in a library in binary format, so that reference blocks
+   are read very fast at application startup.
+
+ */
+QDataStream& operator<<(QDataStream &out, const ReferenceBlock &b) {
+
+  out.setVersion(QDataStream::Qt_5_0);
+
+  QByteArray blockData;
+  QDataStream toWrite(&blockData, QIODevice::WriteOnly);
+
+  toWrite << b.name;
+  toWrite << b.xmlFile;
+  toWrite << b.descriptionBrief;
+  toWrite << b.descriptionDetail;
+  toWrite << b.categories;
+  toWrite << b.hashMd5;
+  toWrite << b.params.size();
+  BlockParameter* p;
+  for(int i=0;i<b.params.size();i++) {
+    p = b.params.at(i);
+    toWrite << p->getContext();
+    toWrite << p->getName();
+    toWrite << p->getTypeString();
+    toWrite << p->getValue().toString();
+    if (p->isPortParameter()) {
+      toWrite << ((BlockParameterPort*)p)->getIfaceName();
+    }
+    else if (p->isWishboneParameter()) {
+      BlockParameterWishbone* pwb = (BlockParameterWishbone*)p;
+      toWrite << pwb->getWidth();
+      toWrite << pwb->getWBAccess();
+      toWrite << pwb->getWBValue();
+      toWrite << pwb->getWBDuration();
+    }
+
+  }
+
+  toWrite << b.inputs.size();
+  for(int i=0; i<b.inputs.size(); i++){
+    ReferenceInterface *iface = (ReferenceInterface *)(b.inputs.at(i));
+    toWrite << iface->getName();
+    toWrite << iface->getWidth();
+    toWrite << iface->getPurpose();
+    toWrite << iface->getDirection();
+    toWrite << iface->getLevel();
+    toWrite << iface->getMultiplicity();
+  }
+  toWrite << b.outputs.size();
+  for(int i=0; i<b.outputs.size(); i++){
+    ReferenceInterface *iface = (ReferenceInterface *)(b.outputs.at(i));
+    toWrite << iface->getName();
+    toWrite << iface->getWidth();
+    toWrite << iface->getPurpose();
+    toWrite << iface->getDirection();
+    toWrite << iface->getLevel();
+    toWrite << iface->getMultiplicity();
+  }
+  toWrite << b.bidirs.size();
+  for(int i=0; i<b.bidirs.size(); i++){
+    ReferenceInterface *iface = (ReferenceInterface *)(b.bidirs.at(i));
+    toWrite << iface->getName();
+    toWrite << iface->getWidth();
+    toWrite << iface->getPurpose();
+    toWrite << iface->getDirection();
+    toWrite << iface->getLevel();
+    toWrite << iface->getMultiplicity();
+  }
+
+  out << blockData;
+
+  return out;
+}
+
+QDataStream& operator>>(QDataStream &in, ReferenceBlock &b) {
+
+  quint32 blockSize;
+  ReferenceInterface* iface;
+  BlockParameter* p;
+  int val;
+  QString txt="";
+
+  in.setVersion(QDataStream::Qt_5_0);
+
+  in >> blockSize;
+
+  in >> b.name;
+  in >> b.xmlFile;
+  in >> b.descriptionBrief;
+  in >> b.descriptionDetail;
+  in >> b.categories;
+  in >> b.hashMd5;
+  b.params.clear();
+  int nb;
+  in >> nb;
+  cout << qPrintable(b.name) << " has " << nb << " parameters" << endl;
+  for(int i=0;i<nb;i++) {
+    QString contextStr = "";
+    QString nameStr= "";
+    QString typeStr = "";
+    QString valueStr = "";
+    in >> contextStr;
+    in >> nameStr;
+    in >> typeStr;
+    in >> valueStr;
+
+    if (contextStr == "user") {
+      p = new BlockParameterUser(&b,nameStr,valueStr);
+    }
+    else if (contextStr == "generic") {
+      p = new BlockParameterGeneric(&b,nameStr,typeStr,valueStr);
+    }
+    else if (contextStr == "port") {
+      QString ifaceStr = "";
+      in >> ifaceStr;
+      p = new BlockParameterPort(&b,nameStr,valueStr,ifaceStr);
+    }
+    else if (contextStr == "wb") {
+      QString widthStr = "";
+      int wbAccess;
+      QString wbValue;
+      int wbDuration;
+      in >> widthStr;
+      in >> wbAccess;
+      in >> wbValue;
+      in >> wbDuration;
+      p = new BlockParameterWishbone(&b,nameStr,typeStr,widthStr,valueStr,wbAccess,wbValue,wbDuration);
+    }
+    b.params.append(p);
+  }
+
+  b.inputs.clear();
+  in >> nb;
+  for(int i=0;i<nb;i++) {
+    iface = new ReferenceInterface(&b);
+    in >> txt;
+    iface->setName(txt);
+    in >> txt;
+    iface->setWidth(txt);
+    in >> val;
+    iface->setPurpose(val);
+    in >> val;
+    iface->setDirection(val);
+    in >> val;
+    iface->setLevel(val);
+    in >> val;
+    iface->setMultiplicity(val);
+    b.inputs.append(iface);
+  }
+
+  b.outputs.clear();
+  in >> nb;
+  for(int i=0;i<nb;i++) {
+    iface = new ReferenceInterface(&b);
+    in >> txt;
+    iface->setName(txt);
+    in >> txt;
+    iface->setWidth(txt);
+    in >> val;
+    iface->setPurpose(val);
+    in >> val;
+    iface->setDirection(val);
+    in >> val;
+    iface->setLevel(val);
+    in >> val;
+    iface->setMultiplicity(val);
+    b.outputs.append(iface);
+  }
+
+  b.bidirs.clear();
+  in >> nb;
+  for(int i=0;i<nb;i++) {
+    iface = new ReferenceInterface(&b);
+    in >> txt;
+    iface->setName(txt);
+    in >> txt;
+    iface->setWidth(txt);
+    in >> val;
+    iface->setPurpose(val);
+    in >> val;
+    iface->setDirection(val);
+    in >> val;
+    iface->setLevel(val);
+    in >> val;
+    iface->setMultiplicity(val);
+    b.bidirs.append(iface);
+  }
+
+  return in;
+}
diff --git a/ReferenceBlock.h b/ReferenceBlock.h
new file mode 100644 (file)
index 0000000..324e289
--- /dev/null
@@ -0,0 +1,69 @@
+#ifndef __REFERENCEBLOCK_H__
+#define __REFERENCEBLOCK_H__
+
+#include <iostream>
+
+#include <QtCore>
+#include <QtGui>
+#include <QtWidgets>
+#include <QtXml>
+
+#include "AbstractBlock.h"
+class AbstractBlock;
+
+#include "BlockImplementation.h"
+
+#include "Exception.h"
+class Exception;
+
+using namespace std;
+using namespace Qt;
+
+
+class ReferenceBlock : public AbstractBlock {
+
+public:
+
+  ReferenceBlock(const QString _xmlFile);
+
+  int getType();
+  inline QString getXmlFile() { return xmlFile; }
+  inline QString getBriefDescription() { return descriptionBrief; }
+  inline QString getDetailedDescription() { return descriptionDetail; }
+  inline QList<int> getCategories() { return categories; }
+  inline QList<BlockImplementation *> getImplementations() { return implementations; }
+  inline QString getHashMd5() { return hashMd5; }
+
+  inline AbstractBlock* getParent() { return NULL; }
+
+  void addCategory(int id);
+  void setBriefDescription(const QString& str);
+  void setDetailedDescription(const QString& str);
+  void addImplementation(BlockImplementation* impl);
+
+  void load(QDomElement &elt) throw(Exception);
+  void setHashMd5();
+
+private:
+  QString xmlFile; // the xml file from which attributes are initialized.
+  QString hashMd5;
+  QString descriptionBrief;
+  QString descriptionDetail;
+  QList<int> categories;
+  QList<BlockImplementation *> implementations; // set when implementations are read
+
+  // loading methods for the different tags in the XML desc.
+  void loadInformations(QDomElement &elt) throw(Exception);
+  void loadParameters(QDomElement &elt) throw(Exception);
+  void loadInterfaces(QDomElement &elt) throw(Exception);
+
+  friend QDataStream &operator<<(QDataStream &out, const ReferenceBlock &b);
+  friend QDataStream &operator>>(QDataStream &in, ReferenceBlock &b);
+
+
+  // AbstractBlock interface
+public:
+  void parametersValidation(QList<AbstractBlock*>* checkedBlocks, QList<AbstractBlock*>* blocksToConfigure);
+};
+
+#endif // __REFERENCEBLOCK_H__
diff --git a/ReferenceInterface.cpp b/ReferenceInterface.cpp
new file mode 100644 (file)
index 0000000..8aca132
--- /dev/null
@@ -0,0 +1,73 @@
+#include "ReferenceInterface.h"
+#include "AbstractBlock.h"
+
+ReferenceInterface::ReferenceInterface(AbstractBlock* _owner)  throw(Exception) : AbstractInterface(_owner) {
+  if (_owner->isReferenceBlock()) throw(Exception(BLOCK_INVALID_TYPE));
+  multiplicity = 1;
+}
+
+ReferenceInterface::ReferenceInterface(AbstractBlock* _owner,
+                                       const QString& _name, const QString&_type,
+                                       const QString& _width,
+                                       int _direction,
+                                       int _purpose,
+                                       int _level,
+                                       int _multiplicity)
+throw (Exception) : AbstractInterface(_owner, _name, _type, _width, _direction, _purpose, _level) {
+
+  if (_owner->isReferenceBlock()) throw(Exception(BLOCK_INVALID_TYPE));
+
+  multiplicity = _multiplicity;
+  if (direction == InOut) {
+    multiplicity = 1;
+  }
+}
+
+bool ReferenceInterface::isReferenceInterface() {
+  return true;
+}
+
+void ReferenceInterface::setMultiplicity(int _multiplicity) {
+  if (direction == InOut) {
+    multiplicity = 1;
+  }
+  else {
+    multiplicity = _multiplicity;
+  }
+}
+
+int ReferenceInterface::translatePurpose(const QString& txt) {
+  if (txt == "clock") {
+    return Clock;
+  }
+  else if (txt == "reset") {
+    return Reset;
+  }
+  if (txt == "wb") {
+    return Wishbone;
+  }
+  return Data;
+}
+
+int ReferenceInterface::translateLevel(const QString& txt) {
+
+  if (txt == "top") {
+    return Top;
+  }
+  return Basic;
+}
+
+int ReferenceInterface::translateMultiplicity(const QString& txt) {
+  bool ok;
+  int mult;
+  if (txt == "*") {
+    mult = -1;
+  }
+  else {
+    mult = txt.toInt(&ok);
+    if (!ok) {
+      mult = 1;
+    }
+  }
+  return mult;
+}
diff --git a/ReferenceInterface.h b/ReferenceInterface.h
new file mode 100644 (file)
index 0000000..cd5bd0f
--- /dev/null
@@ -0,0 +1,48 @@
+#ifndef __REFERENCEINTERFACE_H__
+#define __REFERENCEINTERFACE_H__
+
+#include <iostream>
+
+#include <QtCore>
+#include <QtGui>
+
+#include "AbstractInterface.h"
+
+#include "Exception.h"
+
+using namespace std;
+using namespace Qt;
+
+
+class ReferenceInterface : public AbstractInterface {
+
+public :  
+
+  ReferenceInterface(AbstractBlock *_owner) throw(Exception);
+  ReferenceInterface(AbstractBlock* _owner, const QString& _name, const QString& _type, const QString& _width, int _direction, int _purpose, int _level, int _multiplicity=1) throw (Exception);
+
+  // getters
+  inline int getMultiplicity() { return multiplicity; }
+  inline AbstractInterface* getConnectedFrom() { return NULL; }
+  // setters
+  void setMultiplicity(int _multiplicity);
+
+  // testers
+  bool isReferenceInterface();
+
+  // others
+
+  static int translatePurpose(const QString& txt);
+  static int translateLevel(const QString& txt);
+  static int translateMultiplicity(const QString& txt);
+
+  inline AbstractInterface *clone(){ return NULL; }
+
+
+private:  
+  int multiplicity; // -1 means infinite multiplicity, and X>1, the max. number of instances
+
+
+};
+
+#endif // __REFERENCEINTERFACE_H__
diff --git a/Toto.cpp b/Toto.cpp
new file mode 100644 (file)
index 0000000..0e5fb15
--- /dev/null
+++ b/Toto.cpp
@@ -0,0 +1,12 @@
+#include "Toto.h"
+
+#include "FunctionalBlock.h"
+#include "ReferenceBlock.h"
+#include "ReferenceInterface.h"
+#include "FunctionalInterface.h"
+#include "BlockParameter.h"
+
+
+Toto::Toto(const QString& msg) {
+  v = msg;
+}
diff --git a/Toto.h b/Toto.h
new file mode 100644 (file)
index 0000000..1980e26
--- /dev/null
+++ b/Toto.h
@@ -0,0 +1,35 @@
+#ifndef __TOTO_H__\r
+#define __TOTO_H__\r
+\r
+#include <iostream>\r
+#include <fstream>\r
+\r
+#include <QtCore>\r
+#include <QtXml>\r
+\r
+class ReferenceBlock;\r
+class FunctionalBlock;\r
+class AbstractInterface;\r
+\r
+\r
+#include "ArithmeticEvaluator.h"\r
+class ArithmeticEvaluator;\r
+\r
+#include "Exception.h"\r
+class Exception;\r
+\r
+using namespace std;\r
+using namespace Qt;\r
+\r
+class Toto {\r
+\r
+public:\r
+\r
+  Toto(const QString& msg);\r
+\r
+private:\r
+  QString v;\r
+};\r
+\r
+#endif // __TOTO_H__\r
+\r
diff --git a/blast-tg.odt b/blast-tg.odt
new file mode 100755 (executable)
index 0000000..c85bfeb
Binary files /dev/null and b/blast-tg.odt differ
diff --git a/blast.config b/blast.config
new file mode 100755 (executable)
index 0000000..e0284f4
--- /dev/null
@@ -0,0 +1,2 @@
+// Add predefined macros for your project here. For example:
+// #define THE_ANSWER 42
diff --git a/blast.cpp b/blast.cpp
new file mode 100644 (file)
index 0000000..b205eb2
--- /dev/null
+++ b/blast.cpp
@@ -0,0 +1,18 @@
+#include <QtCore>
+#include <QtGui>
+#include "MainWindow.h"
+#include <iostream>
+
+using namespace std;
+using namespace Qt;
+
+int main(int argc, char *argv[])
+{
+    QApplication a(argc, argv);
+    MainWindow w;
+
+    w.show();
+
+    return a.exec();
+
+}
diff --git a/blast.creator b/blast.creator
new file mode 100755 (executable)
index 0000000..e94cbbd
--- /dev/null
@@ -0,0 +1 @@
+[General]
diff --git a/blast.creator.user b/blast.creator.user
new file mode 100755 (executable)
index 0000000..9b8a007
--- /dev/null
@@ -0,0 +1,193 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE QtCreatorProject>
+<!-- Written by QtCreator 3.2.1, 2017-04-26T13:47:31. -->
+<qtcreator>
+ <data>
+  <variable>EnvironmentId</variable>
+  <value type="QByteArray">{3701e197-5b6c-48ea-9e98-a6cf6de18672}</value>
+ </data>
+ <data>
+  <variable>ProjectExplorer.Project.ActiveTarget</variable>
+  <value type="int">0</value>
+ </data>
+ <data>
+  <variable>ProjectExplorer.Project.EditorSettings</variable>
+  <valuemap type="QVariantMap">
+   <value type="bool" key="EditorConfiguration.AutoIndent">true</value>
+   <value type="bool" key="EditorConfiguration.AutoSpacesForTabs">false</value>
+   <value type="bool" key="EditorConfiguration.CamelCaseNavigation">true</value>
+   <valuemap type="QVariantMap" key="EditorConfiguration.CodeStyle.0">
+    <value type="QString" key="language">Cpp</value>
+    <valuemap type="QVariantMap" key="value">
+     <value type="QByteArray" key="CurrentPreferences">CppGlobal</value>
+    </valuemap>
+   </valuemap>
+   <valuemap type="QVariantMap" key="EditorConfiguration.CodeStyle.1">
+    <value type="QString" key="language">QmlJS</value>
+    <valuemap type="QVariantMap" key="value">
+     <value type="QByteArray" key="CurrentPreferences">QmlJSGlobal</value>
+    </valuemap>
+   </valuemap>
+   <value type="int" key="EditorConfiguration.CodeStyle.Count">2</value>
+   <value type="QByteArray" key="EditorConfiguration.Codec">UTF-8</value>
+   <value type="bool" key="EditorConfiguration.ConstrainTooltips">false</value>
+   <value type="int" key="EditorConfiguration.IndentSize">4</value>
+   <value type="bool" key="EditorConfiguration.KeyboardTooltips">false</value>
+   <value type="int" key="EditorConfiguration.MarginColumn">80</value>
+   <value type="bool" key="EditorConfiguration.MouseHiding">true</value>
+   <value type="bool" key="EditorConfiguration.MouseNavigation">true</value>
+   <value type="int" key="EditorConfiguration.PaddingMode">1</value>
+   <value type="bool" key="EditorConfiguration.ScrollWheelZooming">true</value>
+   <value type="bool" key="EditorConfiguration.ShowMargin">false</value>
+   <value type="int" key="EditorConfiguration.SmartBackspaceBehavior">0</value>
+   <value type="bool" key="EditorConfiguration.SpacesForTabs">true</value>
+   <value type="int" key="EditorConfiguration.TabKeyBehavior">0</value>
+   <value type="int" key="EditorConfiguration.TabSize">8</value>
+   <value type="bool" key="EditorConfiguration.UseGlobal">true</value>
+   <value type="int" key="EditorConfiguration.Utf8BomBehavior">1</value>
+   <value type="bool" key="EditorConfiguration.addFinalNewLine">true</value>
+   <value type="bool" key="EditorConfiguration.cleanIndentation">true</value>
+   <value type="bool" key="EditorConfiguration.cleanWhitespace">true</value>
+   <value type="bool" key="EditorConfiguration.inEntireDocument">false</value>
+  </valuemap>
+ </data>
+ <data>
+  <variable>ProjectExplorer.Project.PluginSettings</variable>
+  <valuemap type="QVariantMap"/>
+ </data>
+ <data>
+  <variable>ProjectExplorer.Project.Target.0</variable>
+  <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">{ed04208c-8774-456b-99b9-4a02094ca7a4}</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">/home/sdomas/Projet/Blast/code/v0.2</value>
+    <valuemap type="QVariantMap" key="ProjectExplorer.BuildConfiguration.BuildStepList.0">
+     <valuemap type="QVariantMap" key="ProjectExplorer.BuildStepList.Step.0">
+      <valuelist type="QVariantList" key="GenericProjectManager.GenericMakeStep.BuildTargets">
+       <value type="QString">all</value>
+      </valuelist>
+      <value type="bool" key="GenericProjectManager.GenericMakeStep.Clean">false</value>
+      <value type="QString" key="GenericProjectManager.GenericMakeStep.MakeArguments"></value>
+      <value type="QString" key="GenericProjectManager.GenericMakeStep.MakeCommand"></value>
+      <value type="bool" key="ProjectExplorer.BuildStep.Enabled">true</value>
+      <value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">Make</value>
+      <value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName"></value>
+      <value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">GenericProjectManager.GenericMakeStep</value>
+     </valuemap>
+     <value type="int" key="ProjectExplorer.BuildStepList.StepsCount">1</value>
+     <value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">Compiler</value>
+     <value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName"></value>
+     <value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">ProjectExplorer.BuildSteps.Build</value>
+    </valuemap>
+    <valuemap type="QVariantMap" key="ProjectExplorer.BuildConfiguration.BuildStepList.1">
+     <valuemap type="QVariantMap" key="ProjectExplorer.BuildStepList.Step.0">
+      <valuelist type="QVariantList" key="GenericProjectManager.GenericMakeStep.BuildTargets">
+       <value type="QString">clean</value>
+      </valuelist>
+      <value type="bool" key="GenericProjectManager.GenericMakeStep.Clean">true</value>
+      <value type="QString" key="GenericProjectManager.GenericMakeStep.MakeArguments"></value>
+      <value type="QString" key="GenericProjectManager.GenericMakeStep.MakeCommand"></value>
+      <value type="bool" key="ProjectExplorer.BuildStep.Enabled">true</value>
+      <value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">Make</value>
+      <value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName"></value>
+      <value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">GenericProjectManager.GenericMakeStep</value>
+     </valuemap>
+     <value type="int" key="ProjectExplorer.BuildStepList.StepsCount">1</value>
+     <value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">Nettoyer</value>
+     <value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName"></value>
+     <value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">ProjectExplorer.BuildSteps.Clean</value>
+    </valuemap>
+    <value type="int" key="ProjectExplorer.BuildConfiguration.BuildStepListCount">2</value>
+    <value type="bool" key="ProjectExplorer.BuildConfiguration.ClearSystemEnvironment">false</value>
+    <valuelist type="QVariantList" key="ProjectExplorer.BuildConfiguration.UserEnvironmentChanges"/>
+    <value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">Défaut</value>
+    <value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName">Défaut</value>
+    <value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">GenericProjectManager.GenericBuildConfiguration</value>
+   </valuemap>
+   <value type="int" key="ProjectExplorer.Target.BuildConfigurationCount">1</value>
+   <valuemap type="QVariantMap" key="ProjectExplorer.Target.DeployConfiguration.0">
+    <valuemap type="QVariantMap" key="ProjectExplorer.BuildConfiguration.BuildStepList.0">
+     <value type="int" key="ProjectExplorer.BuildStepList.StepsCount">0</value>
+     <value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">Déploiement</value>
+     <value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName"></value>
+     <value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">ProjectExplorer.BuildSteps.Deploy</value>
+    </valuemap>
+    <value type="int" key="ProjectExplorer.BuildConfiguration.BuildStepListCount">1</value>
+    <value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">Déployer localement</value>
+    <value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName"></value>
+    <value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">ProjectExplorer.DefaultDeployConfiguration</value>
+   </valuemap>
+   <value type="int" key="ProjectExplorer.Target.DeployConfigurationCount">1</value>
+   <valuemap type="QVariantMap" key="ProjectExplorer.Target.PluginSettings"/>
+   <valuemap type="QVariantMap" key="ProjectExplorer.Target.RunConfiguration.0">
+    <valuelist type="QVariantList" key="Analyzer.Valgrind.AddedSuppressionFiles"/>
+    <value type="bool" key="Analyzer.Valgrind.Callgrind.CollectBusEvents">false</value>
+    <value type="bool" key="Analyzer.Valgrind.Callgrind.CollectSystime">false</value>
+    <value type="bool" key="Analyzer.Valgrind.Callgrind.EnableBranchSim">false</value>
+    <value type="bool" key="Analyzer.Valgrind.Callgrind.EnableCacheSim">false</value>
+    <value type="bool" key="Analyzer.Valgrind.Callgrind.EnableEventToolTips">true</value>
+    <value type="double" key="Analyzer.Valgrind.Callgrind.MinimumCostRatio">0.01</value>
+    <value type="double" key="Analyzer.Valgrind.Callgrind.VisualisationMinimumCostRatio">10</value>
+    <value type="bool" key="Analyzer.Valgrind.FilterExternalIssues">true</value>
+    <value type="int" key="Analyzer.Valgrind.LeakCheckOnFinish">1</value>
+    <value type="int" key="Analyzer.Valgrind.NumCallers">25</value>
+    <valuelist type="QVariantList" key="Analyzer.Valgrind.RemovedSuppressionFiles"/>
+    <value type="int" key="Analyzer.Valgrind.SelfModifyingCodeDetection">1</value>
+    <value type="bool" key="Analyzer.Valgrind.Settings.UseGlobalSettings">true</value>
+    <value type="bool" key="Analyzer.Valgrind.ShowReachable">false</value>
+    <value type="bool" key="Analyzer.Valgrind.TrackOrigins">true</value>
+    <value type="QString" key="Analyzer.Valgrind.ValgrindExecutable">valgrind</value>
+    <valuelist type="QVariantList" key="Analyzer.Valgrind.VisibleErrorKinds">
+     <value type="int">0</value>
+     <value type="int">1</value>
+     <value type="int">2</value>
+     <value type="int">3</value>
+     <value type="int">4</value>
+     <value type="int">5</value>
+     <value type="int">6</value>
+     <value type="int">7</value>
+     <value type="int">8</value>
+     <value type="int">9</value>
+     <value type="int">10</value>
+     <value type="int">11</value>
+     <value type="int">12</value>
+     <value type="int">13</value>
+     <value type="int">14</value>
+    </valuelist>
+    <value type="int" key="PE.EnvironmentAspect.Base">2</value>
+    <valuelist type="QVariantList" key="PE.EnvironmentAspect.Changes"/>
+    <value type="QString" key="ProjectExplorer.CustomExecutableRunConfiguration.Arguments"></value>
+    <value type="QString" key="ProjectExplorer.CustomExecutableRunConfiguration.Executable"></value>
+    <value type="bool" key="ProjectExplorer.CustomExecutableRunConfiguration.UseTerminal">false</value>
+    <value type="QString" key="ProjectExplorer.CustomExecutableRunConfiguration.WorkingDirectory">%{buildDir}</value>
+    <value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">Exécutable personnalisé</value>
+    <value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName"></value>
+    <value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">ProjectExplorer.CustomExecutableRunConfiguration</value>
+    <value type="uint" key="RunConfiguration.QmlDebugServerPort">3768</value>
+    <value type="bool" key="RunConfiguration.UseCppDebugger">false</value>
+    <value type="bool" key="RunConfiguration.UseCppDebuggerAuto">true</value>
+    <value type="bool" key="RunConfiguration.UseMultiProcess">false</value>
+    <value type="bool" key="RunConfiguration.UseQmlDebugger">false</value>
+    <value type="bool" key="RunConfiguration.UseQmlDebuggerAuto">true</value>
+   </valuemap>
+   <value type="int" key="ProjectExplorer.Target.RunConfigurationCount">1</value>
+  </valuemap>
+ </data>
+ <data>
+  <variable>ProjectExplorer.Project.TargetCount</variable>
+  <value type="int">1</value>
+ </data>
+ <data>
+  <variable>ProjectExplorer.Project.Updater.FileVersion</variable>
+  <value type="int">16</value>
+ </data>
+ <data>
+  <variable>Version</variable>
+  <value type="int">16</value>
+ </data>
+</qtcreator>
diff --git a/blast.files b/blast.files
new file mode 100755 (executable)
index 0000000..7b2dd43
--- /dev/null
@@ -0,0 +1,73 @@
+Exception.h
+Exception.cpp
+AbstractBlock.h
+AbstractBlock.cpp
+AbstractBoxItem.h
+AbstractBoxItem.cpp
+FunctionalBlock.cpp
+FunctionalBlock.h
+GroupBlock.h
+GroupBlock.cpp
+BlockImplementation.h
+BlockImplementation.cpp
+GroupScene.cpp
+GroupScene.h
+ReferenceBlock.cpp
+ReferenceBlock.h
+AbstractInterface.h
+AbstractInterface.cpp
+ConnectedInterface.h
+ConnectedInterface.cpp
+ReferenceInterface.h
+ReferenceInterface.cpp
+FunctionalInterface.cpp
+FunctionalInterface.h
+GroupInterface.h
+GroupInterface.cpp
+BlockLibraryWidget.cpp
+BlockLibraryWidget.h
+blast.cpp
+BlockCategory.cpp
+BlockCategory.h
+BoxItem.cpp
+BoxItem.h
+BlockLibraryTree.cpp
+BlockLibraryTree.h
+BlockParameter.cpp
+BlockParameter.h
+BlockParameterUser.h
+BlockParameterUser.cpp
+BlockParameterGeneric.h
+BlockParameterGeneric.cpp
+BlockParameterWishbone.h
+BlockParameterWishbone.cpp
+BlockParameterPort.h
+BlockParameterPort.cpp
+Dispatcher.cpp
+Dispatcher.h
+Graph.cpp
+Graph.h
+MainWindow.cpp
+MainWindow.h
+Parameters.cpp
+Parameters.h
+ConnectionItem.h
+ConnectionItem.cpp
+InterfaceItem.h
+InterfaceItem.cpp
+GroupItem.h
+GroupItem.cpp
+Abstractblockitem.h
+Abstractblockitem.cpp
+GroupWidget.h
+GroupWidget.cpp
+BlockWidget.cpp
+BlockWidget.h
+BlocksToConfigureWidget.h
+BlocksToConfigureWidget.cpp
+ParametersWindow.h
+ParametersWindow.cpp
+ArithmeticEvaluator.cpp
+ArithmeticEvaluator.h
+InterfacePropertiesWindow.h
+InterfacePropertiesWindow.cpp
diff --git a/blast.ico b/blast.ico
new file mode 100755 (executable)
index 0000000..6f1794d
Binary files /dev/null and b/blast.ico differ
diff --git a/blast.includes b/blast.includes
new file mode 100755 (executable)
index 0000000..97e709e
--- /dev/null
@@ -0,0 +1,15 @@
+.
+/usr/include/x86_64-linux-gnu/qt5/QtCore
+/usr/include/x86_64-linux-gnu/qt5/QtGui
+/usr/include/x86_64-linux-gnu/qt5/QtWidgets
+/usr/include/x86_64-linux-gnu/qt5/QtNetwork
+/usr/include/x86_64-linux-gnu/qt5/QtXml
+/usr/include/x86_64-linux-gnu/qt5/QtXmlPatterns
+/usr/include/x86_64-linux-gnu/qt5/QtPrintSupport
+C:\Qt\5.4\mingw491_32\include\QtCore
+C:\Qt\5.4\mingw491_32\include\QtGui
+C:\Qt\5.4\mingw491_32\include\QtWidgets
+C:\Qt\5.4\mingw491_32\include\QtXml
+C:\Qt\5.4\mingw491_32\include\QtXmlPatterns
+C:\Qt\5.4\mingw491_32\include\QtPrintSupport
+C:\MinGW\include
diff --git a/blast.qrc b/blast.qrc
new file mode 100755 (executable)
index 0000000..9f1e539
--- /dev/null
+++ b/blast.qrc
@@ -0,0 +1,24 @@
+<RCC>
+    <qresource>
+        <file>icons/copy.png</file>
+        <file>icons/cut.png</file>
+        <file>icons/delete.png</file>
+        <file>icons/inter_add.png</file>
+        <file>icons/link.png</file>
+        <file>icons/paste.png</file>
+        <file>icons/save.png</file>
+        <file>icons/redo-icon.png</file>
+        <file>icons/undo.png</file>
+        <file>icons/save-as.png</file>
+        <file>icons/open.png</file>
+        <file>icons/load.png</file>
+        <file>icons/window_new.png</file>
+        <file>icons/new.ico</file>
+        <file>icons/folder_add_16.png</file>
+       <file>icons/add_block.png</file>
+       <file>icons/edit_block.png</file>       
+       <file>icons/add_group_void.png</file>
+       <file>icons/add_group_select.png</file>
+       <file>icons/add_connection.png</file>   
+    </qresource>
+</RCC>
diff --git a/blast.rc b/blast.rc
new file mode 100755 (executable)
index 0000000..c6b4512
--- /dev/null
+++ b/blast.rc
@@ -0,0 +1 @@
+IDI_ICON1               ICON    DISCARDABLE     "blast.ico"
\ No newline at end of file
diff --git a/blastconfig.xml b/blastconfig.xml
new file mode 100644 (file)
index 0000000..a8184b8
--- /dev/null
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="UTF-8" standalone="yes" ?>
+<config>
+  <categories nb="6">
+    <category name="root" id="0" parent="-1"/>
+    <category name="math" id="1" parent="0"/>
+    <category name="trigonemetric" id="2" parent="1"/>
+    <category name="multadd" id="3" parent="1"/>
+    <category name="dsp" id="4" parent="0"/>
+    <category name="user" id="5" parent="0"/>
+  </categories>
+
+  <references nb="2" lib_file="/home/sdomas/Projet/Blast/code/v0.2/lib/references/references.bmf" >
+    <reference_lib path="/home/sdomas/Projet/Blast/code/v0.2/" />
+    <reference_lib path="/home/sdomas/Projet/Blast/code/v0.2/lib/references" />
+  </references>
+
+  <implementations nb="1" lib_file="/home/sdomas/Projet/Blast/code/v0.2/lib/implementations/impls.bmf" >
+    <impl_lib path="/home/sdomas/Projet/Blast/code/v0.2/lib/implementations" />
+  </implementations>
+
+  <defaults>
+    <blocks width="175" height="125" font="Helvetica" font_size="14" />
+    <interfaces linelength="10" width="5" height="10" font="Helvetica" font_size="10" />
+    <connections gaplength="20" />
+  </defaults>
+</config>
diff --git a/blastconfig.xsd b/blastconfig.xsd
new file mode 100644 (file)
index 0000000..f254ff6
--- /dev/null
@@ -0,0 +1,210 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema">
+
+
+    <!-- déclaration des groupes d'attributs -->
+
+    <xs:attributeGroup name="categoryAttrGroup">
+       <xs:attribute ref="name" use="required"/>
+       <xs:attribute ref="id" use="required"/>
+       <xs:attribute ref="parent" use="required"/>
+    </xs:attributeGroup>
+
+    <xs:attributeGroup name="blocksAttrGroup">
+       <xs:attribute ref="width" use="required"/>
+       <xs:attribute ref="height" use="required"/>
+       <xs:attribute ref="font" use="required" />
+       <xs:attribute ref="font_size" use="required" />
+    </xs:attributeGroup>
+
+    <xs:attributeGroup name="interfacesAttrGroup">
+       <xs:attribute ref="linelength" use="required" />
+       <xs:attribute ref="width" use="required" />
+       <xs:attribute ref="height" use="required" />
+       <xs:attribute ref="font" use="required" />
+       <xs:attribute ref="font_size" use="required" /> 
+    </xs:attributeGroup>
+
+
+    <!-- déclaration des attributs -->
+
+    <xs:attribute name="nb">
+       <xs:simpleType>
+           <xs:restriction base="xs:nonNegativeInteger">
+               <xs:minInclusive value="1"/>
+           </xs:restriction>
+       </xs:simpleType>
+    </xs:attribute>
+
+    <xs:attribute name="name" type="xs:string"/>
+
+    <xs:attribute name="id">
+       <xs:simpleType>
+           <xs:restriction base="xs:nonNegativeInteger">
+               <xs:minInclusive value="0"/>
+           </xs:restriction>
+       </xs:simpleType>
+    </xs:attribute>
+
+    <xs:attribute name="parent">
+       <xs:simpleType>
+           <xs:restriction base="xs:integer">
+               <xs:minInclusive value="-1"/>
+           </xs:restriction>
+       </xs:simpleType>
+    </xs:attribute>
+
+    <xs:attribute name="path" type="xs:string"/>
+
+    <xs:attribute name="lib_file" type="xs:string"/>
+
+    <xs:attribute name="width">
+       <xs:simpleType>
+           <xs:restriction base="xs:nonNegativeInteger">
+               <xs:minInclusive value="1"/>
+               <xs:maxInclusive value="1000"/>
+           </xs:restriction>
+       </xs:simpleType>
+    </xs:attribute>
+
+    <xs:attribute name="height">
+       <xs:simpleType>
+           <xs:restriction base="xs:nonNegativeInteger">
+               <xs:minInclusive value="1"/>
+               <xs:maxInclusive value="1000"/>
+           </xs:restriction>
+       </xs:simpleType>
+    </xs:attribute>
+
+    <xs:attribute name="font" type="xs:string"/>
+
+    <xs:attribute name="font_size">
+       <xs:simpleType>
+           <xs:restriction base="xs:nonNegativeInteger">
+               <xs:minInclusive value="1"/>
+           </xs:restriction>
+       </xs:simpleType>
+    </xs:attribute>
+
+    <xs:attribute name="linelength">
+       <xs:simpleType>
+           <xs:restriction base="xs:nonNegativeInteger">
+               <xs:minInclusive value="1"/>
+               <xs:maxInclusive value="100"/>
+           </xs:restriction>
+       </xs:simpleType>
+    </xs:attribute>
+
+    <xs:attribute name="gaplength">
+       <xs:simpleType>
+           <xs:restriction base="xs:nonNegativeInteger">
+               <xs:minInclusive value="1"/>
+               <xs:maxInclusive value="100"/>
+           </xs:restriction>
+       </xs:simpleType>
+    </xs:attribute>
+
+
+    <!-- déclaration des groupes d'éléments -->
+
+    <xs:group name="configElmtGroup">
+       <xs:sequence>
+            <xs:element ref="categories"/>
+            <xs:element ref="references"/>
+           <xs:element ref="implementations"/>
+            <xs:element ref="defaults" />
+       </xs:sequence>
+    </xs:group>
+
+    <xs:group name="defaultsElmtGroup">
+       <xs:sequence>
+            <xs:element ref="blocks"/>
+            <xs:element ref="interfaces"/>
+            <xs:element ref="connections" />
+       </xs:sequence>
+    </xs:group>
+
+
+    <!-- déclaration des éléments -->
+
+    <xs:element name="category">
+       <xs:complexType>
+           <xs:attributeGroup ref="categoryAttrGroup" />
+       </xs:complexType>
+    </xs:element>
+
+    <xs:element name="reference_lib">
+       <xs:complexType>
+           <xs:attribute ref="path" use="required"/>
+       </xs:complexType>
+    </xs:element>
+
+    <xs:element name="impl_lib">
+      <xs:complexType>
+       <xs:attribute ref="path" use="required"/>
+      </xs:complexType>
+    </xs:element>
+
+    <xs:element name="blocks">
+       <xs:complexType>
+           <xs:attributeGroup ref="blocksAttrGroup" />
+       </xs:complexType>
+    </xs:element>
+
+    <xs:element name="interfaces">
+       <xs:complexType>
+           <xs:attributeGroup ref="interfacesAttrGroup" />
+       </xs:complexType>
+    </xs:element>
+
+    <xs:element name="connections">
+       <xs:complexType>
+           <xs:attribute ref="gaplength" use="required"/>
+       </xs:complexType>
+    </xs:element>
+
+    <xs:element name="categories">
+        <xs:complexType>
+            <xs:sequence>
+                <xs:element ref="category" maxOccurs="unbounded" />
+            </xs:sequence>
+           <xs:attribute ref="nb" use="required"/>
+        </xs:complexType>
+    </xs:element>
+
+    <xs:element name="references">
+        <xs:complexType >
+            <xs:sequence>
+                <xs:element ref="reference_lib" maxOccurs="unbounded" />
+            </xs:sequence>
+           <xs:attribute ref="nb" use="required"/>
+           <xs:attribute ref="lib_file" use="required"/>
+        </xs:complexType>
+    </xs:element>
+
+    <xs:element name="implementations">
+        <xs:complexType >
+            <xs:sequence>
+                <xs:element ref="impl_lib" maxOccurs="unbounded" />
+            </xs:sequence>
+           <xs:attribute ref="nb" use="required"/>
+           <xs:attribute ref="lib_file" use="required"/>
+        </xs:complexType>
+    </xs:element>
+
+    <xs:element name="defaults">
+        <xs:complexType>
+           <xs:group ref="defaultsElmtGroup" />
+        </xs:complexType>      
+    </xs:element>
+
+
+    <!-- Racine du document -->
+
+    <xs:element name="config">
+        <xs:complexType>
+           <xs:group ref="configElmtGroup" />
+        </xs:complexType>      
+    </xs:element>
+
+</xs:schema>
diff --git a/block-1I1O.xml b/block-1I1O.xml
new file mode 100644 (file)
index 0000000..32efdb5
--- /dev/null
@@ -0,0 +1,34 @@
+<?xml version="1.0" encoding="UTF-8" standalone="yes" ?>
+<block>
+  <informations>
+    <name>
+      block-1I1O
+    </name>
+    <category ids="1,4" />  
+    <description>
+      <brief>
+       A testing block with 1 input, 1 output
+      </brief>
+      <detailed>
+       A testing block with 1 input, 1 output
+      </detailed>     
+    </description>    
+  </informations>
+
+  <parameters>
+    <parameter name="data_width" type="string" value="8" context="user"/>
+  </parameters>
+
+  <interfaces>
+    <inputs>
+      <input name="clk" width="1" purpose="clock" />
+      <input name="rst" width="1" purpose="reset" />
+      
+      <input name="data_i" width="$data_width"/>      
+    </inputs>
+    <outputs>
+      <output name="data_o" width="$data_width"/>
+    </outputs>
+  </interfaces>
+
+</block>
diff --git a/block-2I2O.xml b/block-2I2O.xml
new file mode 100644 (file)
index 0000000..54c5460
--- /dev/null
@@ -0,0 +1,36 @@
+<?xml version="1.0" encoding="UTF-8" standalone="yes" ?>
+<block>
+  <informations>
+    <name>
+      block-2I2O
+    </name>
+    <category ids="1,4" />  
+    <description>
+      <brief>
+       A testing block with 2 inputs, 2 outputs
+      </brief>
+      <detailed>
+       A testing block with 2 inputs, 2 outputs
+      </detailed>     
+    </description>    
+  </informations>
+
+  <parameters>
+    <parameter name="data_width" type="string" value="8" context="user"/>
+  </parameters>
+
+  <interfaces>
+    <inputs>
+      <input name="clk" width="1" purpose="clock" />
+      <input name="rst" width="1" purpose="reset" />
+      
+      <input name="data1_i" width="$data_width"/>
+      <input name="data2_i" width="$data_width"/>      
+    </inputs>
+    <outputs>
+      <output name="data1_o" width="$data_width"/>
+      <output name="data2_o" width="$data_width"/>      
+    </outputs>
+  </interfaces>
+
+</block>
diff --git a/block-2INO.xml b/block-2INO.xml
new file mode 100644 (file)
index 0000000..d654234
--- /dev/null
@@ -0,0 +1,35 @@
+<?xml version="1.0" encoding="UTF-8" standalone="yes" ?>
+<block>
+  <informations>
+    <name>
+      block-2INO
+    </name>
+    <category ids="1,4" />  
+    <description>
+      <brief>
+       A testing block with 2 inputs, N outputs
+      </brief>
+      <detailed>
+       A testing block with 2 inputs,  N outputs
+      </detailed>     
+    </description>    
+  </informations>
+
+  <parameters>
+    <parameter name="data_width" type="string" value="8" context="user"/>
+  </parameters>
+
+  <interfaces>
+    <inputs>
+      <input name="clk" width="1" purpose="clock" />
+      <input name="rst" width="1" purpose="reset" />
+      
+      <input name="data1_i" width="$data_width"/>
+      <input name="data2_i" width="$data_width"/>      
+    </inputs>
+    <outputs>
+      <output name="data_o" width="$data_width" multiplicity="*"/>
+    </outputs>
+  </interfaces>
+
+</block>
diff --git a/block.xsd b/block.xsd
new file mode 100644 (file)
index 0000000..42c82ef
--- /dev/null
+++ b/block.xsd
@@ -0,0 +1,190 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema">
+
+    <!-- déclaration des groupes d'attributs -->
+
+    <xs:attributeGroup name="parameterAttrGroup">
+       <xs:attribute ref="name" use="required"/>
+       <xs:attribute ref="type" use="required"/>
+       <xs:attribute ref="wishbone" use="optional"/>
+       <xs:attribute ref="core" use="optional"/>
+       <xs:attribute ref="value" use="optional"/>
+       <xs:attribute ref="iface" use="optional"/>
+       <xs:attribute ref="width" use="optional"/>      
+       <xs:attribute ref="context" use="required"/>
+    </xs:attributeGroup>
+
+    <xs:attributeGroup name="inOutAttrGroup">
+       <xs:attribute ref="name" use="required"/>
+       <xs:attribute ref="width" use="required"/>
+       <xs:attribute ref="type"/>
+       <xs:attribute ref="level"/>
+       <xs:attribute ref="purpose"/>
+       <xs:attribute ref="multiplicity"/>
+    </xs:attributeGroup>
+
+
+    <!-- déclaration des attributs -->
+
+    <xs:attribute name="ids" type="xs:string"/>
+    <xs:attribute name="name" type="xs:string"/>
+    <xs:attribute name="type" type="xs:string"/>
+    <xs:attribute name="core" type="xs:string"/>
+    <xs:attribute name="wishbone" type="xs:string"/>
+    <xs:attribute name="context" type="xs:string" />
+    <xs:attribute name="level" type="xs:string" />
+    <xs:attribute name="multiplicity" type="xs:string" />
+    <xs:attribute name="width" type="xs:string"/>
+    <xs:attribute name="purpose" type="xs:string"/>
+    <xs:attribute name="value" type="xs:string"/>
+    <xs:attribute name="iface" type="xs:string"/>
+    <xs:attribute name="path" type="xs:string" />
+
+
+    <!-- déclaration des groupes d'éléments -->
+
+    <xs:group name="blockElmtGroup">
+       <xs:sequence>
+            <xs:element ref="informations"/>
+            <xs:element ref="parameters"/>
+            <xs:element ref="interfaces"/>
+            <xs:element ref="implementations" minOccurs="0"/>
+       </xs:sequence>
+    </xs:group>
+
+    <xs:group name="informationsElmtGroup">
+       <xs:sequence>
+           <xs:element ref="name"/>
+           <xs:element ref="category"/>
+           <xs:element ref="description"/>
+       </xs:sequence>
+    </xs:group>
+
+    <xs:group name="descriptionElmtGroup">
+       <xs:sequence>
+           <xs:element ref="brief"/>
+           <xs:element ref="detailed"/>
+       </xs:sequence>
+    </xs:group>
+
+    <xs:group name="interfacesElmtGroup">
+       <xs:sequence>
+           <xs:element ref="inputs" minOccurs="0"/>
+           <xs:element ref="outputs" minOccurs="1"/>
+           <xs:element ref="bidirs" minOccurs="0"/>
+       </xs:sequence>
+    </xs:group>
+
+
+    <!-- déclaration des éléments -->
+
+    <xs:element name="informations">
+       <xs:complexType>
+           <xs:group ref="informationsElmtGroup"/>
+       </xs:complexType>
+    </xs:element>
+
+    <xs:element name="name" type="xs:string" />
+
+    <xs:element name="category">
+       <xs:complexType>
+           <xs:attribute ref="ids" use="required"/>
+       </xs:complexType>
+    </xs:element>
+
+    <xs:element name="description">
+       <xs:complexType>
+           <xs:group ref="descriptionElmtGroup"/>
+       </xs:complexType>
+    </xs:element>
+
+    <xs:element name="brief" type="xs:string" />
+
+    <xs:element name="detailed" type="xs:string" />
+
+    <xs:element name="parameters">
+       <xs:complexType>
+           <xs:sequence>
+               <xs:element ref="parameter" minOccurs="0" maxOccurs="unbounded"/>
+           </xs:sequence>
+       </xs:complexType>
+    </xs:element>
+
+    <xs:element name="parameter">
+       <xs:complexType>
+           <xs:attributeGroup ref="parameterAttrGroup"/>
+       </xs:complexType>
+    </xs:element>
+
+    <xs:element name="interfaces">
+       <xs:complexType>
+           <xs:group ref="interfacesElmtGroup"/>
+       </xs:complexType>
+    </xs:element>
+
+    <xs:element name="inputs">
+       <xs:complexType>
+           <xs:sequence>
+               <xs:element ref="input" maxOccurs="unbounded" />
+           </xs:sequence>
+       </xs:complexType>
+    </xs:element>
+
+    <xs:element name="input">
+       <xs:complexType>
+           <xs:attributeGroup ref="inOutAttrGroup"/>
+       </xs:complexType>
+    </xs:element>
+
+    <xs:element name="outputs">
+       <xs:complexType>
+           <xs:sequence>
+               <xs:element ref="output" maxOccurs="unbounded" />
+           </xs:sequence>
+       </xs:complexType>
+    </xs:element>
+
+    <xs:element name="output">
+       <xs:complexType>
+           <xs:attributeGroup ref="inOutAttrGroup"/>
+       </xs:complexType>
+    </xs:element>
+
+    <xs:element name="bidirs">
+       <xs:complexType>
+           <xs:sequence>
+               <xs:element ref="bidir" maxOccurs="unbounded" />
+           </xs:sequence>
+       </xs:complexType>
+    </xs:element>
+
+    <xs:element name="bidir">
+       <xs:complexType>
+           <xs:attributeGroup ref="inOutAttrGroup"/>
+       </xs:complexType>
+    </xs:element>
+
+    <xs:element name="implementations">
+       <xs:complexType>
+           <xs:sequence>
+               <xs:element ref="implementation" maxOccurs="unbounded" />
+           </xs:sequence>
+       </xs:complexType>
+    </xs:element>
+
+    <xs:element name="implementation">
+       <xs:complexType>
+           <xs:attribute ref="path" use="required" />
+       </xs:complexType>
+    </xs:element>
+
+
+    <!-- Racine du document -->
+
+    <xs:element name="block">
+       <xs:complexType>
+           <xs:group ref="blockElmtGroup"/>
+       </xs:complexType>
+    </xs:element>
+
+</xs:schema>
diff --git a/doc/models-tg.pdf b/doc/models-tg.pdf
new file mode 100644 (file)
index 0000000..86606a7
Binary files /dev/null and b/doc/models-tg.pdf differ
diff --git a/doc/models-tg.tex b/doc/models-tg.tex
new file mode 100644 (file)
index 0000000..fd39c6f
--- /dev/null
@@ -0,0 +1,376 @@
+\documentclass[12pt,fleqn,a4paper]{article}
+\usepackage[latin1]{inputenc}
+%\usepackage[cyr]{aeguill}
+\usepackage{xspace}
+\usepackage{amsmath}
+\usepackage{amsfonts}
+\usepackage[english]{babel}
+\usepackage{url}
+\usepackage{multirow}
+\let\urlorig\url
+\renewcommand{\url}[1]{%
+  \begin{otherlanguage}{english}\urlorig{#1}\end{otherlanguage}%
+}
+
+%\usepackage{pstricks,pst-node,pst-text,pst-3d}
+\usepackage{graphicx}
+\usepackage{thumbpdf}
+\usepackage{color}
+\usepackage{moreverb}
+%\usepackage{commath}
+\usepackage{subfigure}
+%\input{psfig.sty}
+\usepackage{fullpage}
+\usepackage{fancybox}
+
+\usepackage[ruled,lined,linesnumbered]{algorithm2e}
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%% LyX specific LaTeX commands.
+\newcommand{\noun}[1]{\textsc{#1}}
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%% my own LaTeX commands.
+%\newcommand{\bibpath}[1]
+%        {/home/sdomas/rapport/eigenjace/ipdps/#1}
+
+\newcommand{\tab}{\ \ \ }
+\newcommand{\ot}[1]{{\tt #1}}
+%%%%%%%%%%%%%%%%%%%%%%%%%%%% my bib path.
+
+
+\title{BLAST: classes and xml files for blocks (models, implementations and view)}
+
+\author{St\'ephane Domas\\
+Laboratoire d'Informatique
+de l'Universit\'e de  Franche-Comt\'e, \\
+BP 527, \\
+90016~Belfort CEDEX, France\\}
+
+
+
+\begin{document}
+
+\maketitle
+
+\thispagestyle{empty}
+\section{What are blocks and items ?}
+A block is the main unit to build a design in Blast. From the user
+point of view, a block represents a process with inputs to consume
+data, outputs to produce results. It may have some parameters
+(e.g. the input/output data size). Thus, the user is not concerned
+about how the block is really implemented in VHDL, just about the
+"function" of the block. Some blocks are predefined, but the user can
+also build them by composing predefined ones.
+
+For the first type, the user has to choose the predefined blocks from
+a library of "reference blocks" that do a particular processing
+(i.e. a multiplication, a filter, ...), with default interface names
+and parameter values. To add such a block to the design, a reference
+block is cloned to obtain a "functional" block. It is similar to the
+instanciation in object oriented programming: reference block
+corresponds to the class, and functional block to the instance of that
+class. Thus, a design may contain several functional blocks that
+correspond to the same reference block. A reference block is
+associated to one or several implementations that are in fact patterns
+of VHDL code. One of them will be chosen more or less automatically by
+Blast to produce the final VHDL code. The representation of an
+implementation as a class and the structure of the files that contain
+patterns are discussed in details in Section \ref{Implementations}.
+
+The second type is named a "group" block. It is created empty or with
+a set of existing functional blocks. For example, when a void design
+is created, a group block is also created, that will represent the top
+component in the VHDL code. User can add predefined blocks or even
+other group blocks within a group very easily. There main purpose is
+to make the design clearer and the VHDL more readable. Indeed, each
+group will be translated into a VHDL component. Thus, instead of
+having a single top component with a bunch of predefined blocks
+within, they can be spread within groups to build a design
+hierachically.
+
+These three types of block are represented by a hierarchy of classes
+that is described in details in Section \ref{sec:blocks_class}.\\
+
+Reference, functional and group blocks are just containers of data,
+i.e. they are part of the Model in MVC paradigm). The two latter have
+a graphical counter part, named items, so that they can be represented
+in the graphical interface. The hierarchy of classes
+that represents the items is described in details in Section \ref{sec:items_class}.\\
+
+\section{Class hierarchy for blocks}
+\label{sec:blocks_class}
+
+\subsection{the top class}
+\label{sec:abstract_block_class}
+
+The top class for describing block is {\tt AbstractBlock}, derived in
+three subclasses: {\tt ReferenceBlock}, {\tt FunctionalBlock}, {\tt
+  GroupBlock}.
+
+Some attributes are common to every types, and defined in {\tt AbstractBlock}:
+\begin{itemize}  
+\item a name,
+\item parameters,
+\item input/output/bidirectional interfaces.
+\end{itemize}
+
+Parameters and interfaces are complex to represent and thus, are also
+described by a hierarchy of classes in Section
+\ref{sec:parameters_class} and \ref{sec:interfaces_class}.
+
+\subsection{reference blocks}
+\label{sec:reference_block_class}
+
+A reference block is created taking informations in an XML file that
+describes it, providing its parameters and interfaces. The structure
+of that file is described in details in Section
+\ref{sec:references_xml}.
+
+A reference block also contains a list of {\tt
+  BlockImplementation}. Each of them represents a pattern of VHDL code
+that implements the function of the block.
+
+\subsection{functional blocks}
+\label{sec:functional_block_class}
+
+A functional block has two attributes {\tt reference} and {\tt group}
+that respectively refer to the reference block that has been cloned to
+create that functional block, and the group block that contains it.
+
+
+\subsection{group blocks}
+\label{sec:group_block_class}
+
+A group block has mainly two attributes {\tt parent} and {\tt
+  blocks}. The first one is a pointer to the group that contains that
+group (or {\tt NULL} if it is the top group). The second one is the
+list of the functional or group blocks that are within this group.
+
+{\bf Important: } a group block has no interface by itself. In fact,
+they are created when the user wants to connect an interface of a
+inner block to the outside of the block. Note that there is a 1:1
+relation between a group interface and an interface of an inner
+block. Nevertheless, an output group interface can still be connected
+to several input interfaces.
+
+{\bf Important: } a group block has no parameters by itself, except
+if it contains blocks that may be configured via a wishbone. In this
+case, the generic parameters to manage the wishbone are atuomaticcaly
+added to the group.
+
+\subsection{interfaces classes}
+\label{sec:interfaces_class}
+
+As for blocks, a top class {\tt AbstractInterface} represents the
+common features of all interfaces and it is derived in three
+subclasses: {\tt ReferenceInterface}, {\tt FunctionalInterface} and
+{\tt GroupInterface}.
+
+\subsection{parameters classes}
+\label{sec:parameters_class}
+
+
+There are four types of parameters for a block:
+\begin{itemize}  
+\item user,
+\item generic,
+\item port,
+\item wishbone.  
+\end{itemize}
+
+These are represented by the top class {\tt BlockParameter} and four
+subclasses: ({\tt BlockParameterUSer}, {\tt BlockParameterGeneric},
+{\tt BlockParameterPort}, {\tt BlockParameterWishbone}.
+
+Four attributes are common to all, and defined in {\tt BlockParameter}:
+\begin{itemize}  
+\item \ot{owner}: a pointer to the block instance (reference/functional) that ``owns'' this parameter,
+\item \ot{name}: the name of the parameter (NB: cannot be changed by the user of BLAST),
+\item \ot{type}: the type of the value,
+\item \ot{value}: the default value of the parameter, given as a \ot{QString} but stored as a \ot{QVariant}.
+\end{itemize}
+
+\ot{type} value (int) must be set with one of those in \ot{ParamType} enum (cf. \ot{BlockParameter.h}):
+
+\begin{verbatim}
+enum ParamType { Undefined = -1, Expression = 1, Character, 
+                 String, Bit, BitVector, Boolean, 
+                 Integer, Natural, Positive, Real, Time};
+\end{verbatim}
+Except the two first, these values correspond to predefined types in
+VHDL. \ot{Expression} correspond to an arithmetic expression and must
+be used only for port and wishbone parameters. Thus, its syntax will
+be presented in the associated sections (\ref{sec:parameters_port} and
+\ref{parameters_wb}).\\
+
+Whatever the case, parameters will be used during VHDL generation but at different phases, depending on the class.
+
+\subsubsection{user parameters}
+\label{sec:parameters_user}
+User parameters have a type equals to \ot{String}. A default value
+must be given at construction but a \ot{userValue} can be defined via
+setters.\\
+
+A user parameter is only used when generating the VHDL code of the
+architecture section of a block (cf. section
+\ref{sec:impls_xml}). Each time the generator encounters an escape
+sequence: \ot{@val\{user\_parameter\_name\}}, it replaces it with
+\ot{userValue} if defined, or with the default value.\\
+
+{\bf CAUTION:} No validity check are done by BLAST on default and user
+value strings. Thus, they can be anything and can lead to incorrect
+VHDL.
+
+\subsubsection{generic parameters}
+\label{sec:parameters_generic}
+
+Generic parameters have a type equals to any predefined VHDL type (i.e. all
+defined above except \ot{Undefined} and \ot{Expression}). A default
+value must be given at construction but a \ot{userValue} can be
+defined via setters.\\
+
+A generic parameter is used during the generation of:
+\begin{itemize}
+\item the entity section,
+\item the component section when the owner block is used within another block,
+\item the generic map of when instanciating owner block is used within another block,
+\item the architecture section.
+\end{itemize}
+
+In the two first cases, it leads to lines like
+
+\ot{d\_width : integer := 16;}, using the \ot{name}, \ot{type} and default value.
+
+In the third case, it leads to lines like
+
+\ot{d\_width => 10,}, using the \ot{name} and \ot{userValue},
+or default value if not defined.
+
+\ot{d\_width => d\_width,}, using only the
+\ot{name}. This case occurs when the owner is instanciated within a
+block that has a generic parameter with the same name.
+
+In the last case, each time the generator encounters an escape
+sequence: \ot{@val\{generic\_parameter\_name\}}, it replaces it with
+\ot{userValue} if defined, or with the default value.\\
+
+{\bf IMPORTANT:} a block that defines wishbone parameters will be
+generated with 2 generic parameters with predefined names:
+\ot{wb\_data\_width} and \ot{wb\_addr\_width}. They correspond to the
+width of the address and data buses of the wishbone and are used
+during the generation of the controller of the block
+(cf. \ref{sec:parameters_wb}).
+
+\subsubsection{port parameters}
+\label{sec:parameters_port}
+A port parameter can be used to obtain a value associated to an
+interface of the block. Indeed, it is possible to create several
+instances of the same interface, when its multiplicity given in the
+reference model is greater than 1. For example, it is used for block
+that may have a variable number of inputs/outputs, like a
+multiplexer. Instead fo creating a bunch of multiplexers with 2, 3, 4,
+$\ldots$ data inputs, it is possible to generate one for any
+amount. In BLAST, this amount is given by the number of instances of
+the data input the user has created. It implies that the selector
+input has a variable range and thus needs a variable number of bits to
+be expressed. If $N$ is the number of instances of the data input,
+then the selector size is $log_2(N)$. A port parameter is used to
+express such a value.\\
+
+A port parameters have a supplementary attribute \ot{ifaceName} that
+must correspond to an existing interface of the block. \ot{type} is
+equal to \ot{Expression} and \ot{value} contains this expression,
+using variables with a predefined name \ot{\$if\_nb} and
+\ot{\$if\_width} that will be respectively replace during VHDL
+generation by the number of instances of \ot{ifaceName}, and its
+width.
+
+A port parameter is used during the generation of:
+\begin{itemize}
+\item the entity section,
+\item the component section when the owner block is used within another block,
+\item the architecture section.
+\end{itemize}
+
+In every case, each time the generator encounters an escape sequence:
+\ot{@val\{port\_parameter\_name\}}, it replaces it with the computed
+value of the parameter using the expression and the interface name.
+
+
+\subsubsection{wishbone parameters}
+\label{sec:parameters_wb}
+
+A wishbone parameter corresponds to a register that can be read/write
+via the wishbone bus. Nevertheless, the GUI allows the user to disable
+the wishbone access and replace it by a fixed value or a port that is
+assign to the register.
+
+Since a register has a width, \ot{type} gives its type. Valid types are:
+\begin{itemize}
+\item \ot{boolean} if the register is an \ot{std\_logic},
+\item \ot{natural} if the register has a fixed width and is a \ot{std\_logic\_vector},
+\item \ot{expression} if the register has a variable width and is a \ot{std\_logic\_vector},  
+\end{itemize}
+The width is given in a supplementary attribute \ot{width}. Note that:
+\begin{itemize}
+\item if the type is boolean, width should be equal to 1 but in fact is not used.
+
+\item if the type is natural and width is equal to 1, it leads to
+\ot{std\_logic\_vector(0 downto 0)}, which is sometimes usefull for
+memory accesses.
+
+\item if the type is an expression, width must contains an expression
+  using only +,-,*, numbers and generic parameter references
+  (i.e. parameter name prepend with a $). No check is done thus, the
+  model must be correct so that valid VHDL will be produced.
+\end{itemize}
+
+In the second case, the expression may use predefined names
+\ot{wb\_data\_width} and \ot{wb\_addr\_width}.
+
+Whatever the case, during VHDL generation, the final width will be
+compared to the wishbone data bus width. If the bus width is lesser
+than the register width, then several wishbone accesses are needed to
+read/write the register. For example, if wishbone width is 16 and a
+register has a width of 20, we need to define two addresses, one to
+access to bits 0 to 15, and one for bits 16 to 19. The total number of
+needed addresses gives the minimal width of the address bus (i.e. log2(nb addr)).\\
+
+The value is a initialization value. If not provided, it is 0 by
+default.\\
+
+Three other attributes are declared:
+\begin{itemize}
+\item \ot{wbAccess}: indicates if the register is written or read by
+  the wishbone bus. Thus, if it is written, the register is an input
+  of the block and if it is read, the block provides its value.
+\item \ot{wbValue}: it may be a natural, a boolean, or the word
+  data. In the two first cases, the given value is affected to the
+  register as soon as the register is accessed in writing. In the
+  third case, the register is affected with the value that is provided
+  on the wishbone data bus.
+\item \ot{wbDuration} : indicates if the affectation is permanent or
+  just a trigger. In the second case, the value is set for just one
+  clock cycle and then reset to the initialization value given by the
+  \ot{value} attribute.\\
+\end{itemize}
+
+A wishbone parameter is used during the generation of:
+\begin{itemize}
+\item the controller of the block (NB: this generation is done at the block level),
+\item the entity section, because register values are in fact read/write by the block via input/output ports,
+\item the component section when the owner block is used within another block.
+\end{itemize}
+
+\section{Implementations XML description}
+\label{sec:impls_xml}
+
+\section{Implementations class hierarchy}
+\label{sec:impls_class}
+
+
+\end{document}
+
+
+
+
+
diff --git a/icons/add_block.png b/icons/add_block.png
new file mode 100644 (file)
index 0000000..6a12252
Binary files /dev/null and b/icons/add_block.png differ
diff --git a/icons/add_block.svg b/icons/add_block.svg
new file mode 100644 (file)
index 0000000..e1a8dc3
--- /dev/null
@@ -0,0 +1,155 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!-- Created with Inkscape (http://www.inkscape.org/) -->
+
+<svg
+   xmlns:dc="http://purl.org/dc/elements/1.1/"
+   xmlns:cc="http://creativecommons.org/ns#"
+   xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+   xmlns:svg="http://www.w3.org/2000/svg"
+   xmlns="http://www.w3.org/2000/svg"
+   xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+   xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+   width="54.086605"
+   height="39"
+   id="svg2"
+   version="1.1"
+   inkscape:version="0.48.5 r10040"
+   sodipodi:docname="add_block.svg"
+   inkscape:export-filename="/home/sdomas/Projet/Blast/code/v0.2/icons/add_block.png"
+   inkscape:export-xdpi="300"
+   inkscape:export-ydpi="300">
+  <defs
+     id="defs4">
+    <linearGradient
+       id="linearGradient5732">
+      <stop
+         style="stop-color:#000000;stop-opacity:1;"
+         offset="0"
+         id="stop5734" />
+      <stop
+         style="stop-color:#000000;stop-opacity:0.78195488;"
+         offset="1"
+         id="stop5736" />
+    </linearGradient>
+    <linearGradient
+       id="linearGradient4248">
+      <stop
+         style="stop-color:#205026;stop-opacity:1;"
+         offset="0"
+         id="stop4250" />
+      <stop
+         id="stop4256"
+         offset="1"
+         style="stop-color:#285e31;stop-opacity:0.49803922;" />
+    </linearGradient>
+  </defs>
+  <sodipodi:namedview
+     id="base"
+     pagecolor="#ffffff"
+     bordercolor="#666666"
+     borderopacity="1.0"
+     inkscape:pageopacity="0.0"
+     inkscape:pageshadow="2"
+     inkscape:zoom="11.313708"
+     inkscape:cx="46.8372"
+     inkscape:cy="26.47285"
+     inkscape:document-units="px"
+     inkscape:current-layer="layer1"
+     showgrid="true"
+     inkscape:window-width="1454"
+     inkscape:window-height="800"
+     inkscape:window-x="435"
+     inkscape:window-y="130"
+     inkscape:window-maximized="0"
+     fit-margin-top="0"
+     fit-margin-left="0"
+     fit-margin-right="0"
+     fit-margin-bottom="0"
+     borderlayer="true"
+     inkscape:showpageshadow="true">
+    <inkscape:grid
+       type="xygrid"
+       id="grid5846"
+       units="px"
+       empspacing="5"
+       visible="true"
+       enabled="true"
+       snapvisiblegridlinesonly="true"
+       spacingx="1px"
+       spacingy="1px"
+       originx="0.543305px"
+       originy="-7.4999995px" />
+  </sodipodi:namedview>
+  <metadata
+     id="metadata7">
+    <rdf:RDF>
+      <cc:Work
+         rdf:about="">
+        <dc:format>image/svg+xml</dc:format>
+        <dc:type
+           rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
+        <dc:title></dc:title>
+      </cc:Work>
+    </rdf:RDF>
+  </metadata>
+  <g
+     inkscape:label="Calque 1"
+     inkscape:groupmode="layer"
+     id="layer1"
+     transform="translate(-50.550445,-21.358244)">
+    <rect
+       style="color:#000000;fill:none;stroke:#000000;stroke-width:3;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+       id="rect2987"
+       width="26.574802"
+       height="32.401573"
+       x="64.117371"
+       y="22.858244" />
+    <path
+       style="fill:none;stroke:#000000;stroke-width:2;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
+       d="m 91.235473,37.858244 8.858277,0"
+       id="path3757"
+       inkscape:connector-curvature="0" />
+    <path
+       style="fill:none;stroke:#000000;stroke-width:2;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
+       d="m 55.09375,30.858244 8.858268,0"
+       id="path4203"
+       inkscape:connector-curvature="0" />
+    <path
+       style="fill:#000000;fill-opacity:1;stroke:#000000;stroke-width:2;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
+       d="m 100.09375,36.086591 0,3.543307 3.5433,-1.771654 z"
+       id="path4205"
+       inkscape:connector-curvature="0" />
+    <path
+       style="fill:#000000;fill-opacity:1;stroke:#000000;stroke-width:2;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
+       d="m 51.550445,29.086591 0,3.543307 3.543305,-1.771654 z"
+       id="path4205-7"
+       inkscape:connector-curvature="0" />
+    <path
+       style="fill:none;stroke:#000000;stroke-width:2;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
+       d="m 55.259102,48.173205 8.858268,0"
+       id="path4203-5"
+       inkscape:connector-curvature="0" />
+    <path
+       style="fill:#000000;fill-opacity:1;stroke:#000000;stroke-width:2;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
+       d="m 51.715795,46.401549 0,3.543307 3.543305,-1.771654 z"
+       id="path4205-7-0"
+       inkscape:connector-curvature="0" />
+    <text
+       xml:space="preserve"
+       style="font-size:16px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:center;line-height:125%;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:middle;fill:#000000;fill-opacity:1;stroke:none;font-family:Wingdings;-inkscape-font-specification:Wingdings"
+       x="77.09375"
+       y="31.858244"
+       id="text5848"
+       sodipodi:linespacing="125%"><tspan
+         sodipodi:role="line"
+         id="tspan5850"
+         x="77.09375"
+         y="31.858244"
+         style="font-size:6px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:center;line-height:125%;writing-mode:lr-tb;text-anchor:middle;font-family:Wingdings;-inkscape-font-specification:Wingdings">bloc</tspan></text>
+    <path
+       style="color:#000000;fill:#3bb21f;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:1;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+       d="m 81.09375,35.858244 c -1.108,0 -2,0.892 -2,2 l 0,6 -6,0 c -1.108,0 -2,0.892 -2,2 l 0,4 c 0,1.108 0.892,2 2,2 l 6,0 0,6 c 0,1.108 0.892,2 2,2 l 4,0 c 1.108,0 2,-0.892 2,-2 l 0,-6 6,0 c 1.108,0 2,-0.892 2,-2 l 0,-4 c 0,-1.108 -0.892,-2 -2,-2 l -6,0 0,-6 c 0,-1.108 -0.892,-2 -2,-2 l -4,0 z"
+       id="rect4258-34"
+       inkscape:connector-curvature="0" />
+  </g>
+</svg>
diff --git a/icons/add_connection.png b/icons/add_connection.png
new file mode 100644 (file)
index 0000000..cb67913
Binary files /dev/null and b/icons/add_connection.png differ
diff --git a/icons/add_connection.svg b/icons/add_connection.svg
new file mode 100644 (file)
index 0000000..e3e93ae
--- /dev/null
@@ -0,0 +1,123 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!-- Created with Inkscape (http://www.inkscape.org/) -->
+
+<svg
+   xmlns:dc="http://purl.org/dc/elements/1.1/"
+   xmlns:cc="http://creativecommons.org/ns#"
+   xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+   xmlns:svg="http://www.w3.org/2000/svg"
+   xmlns="http://www.w3.org/2000/svg"
+   xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+   xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+   width="39.03125"
+   height="32.875"
+   id="svg2"
+   version="1.1"
+   inkscape:version="0.48.5 r10040"
+   sodipodi:docname="add_connection.svg"
+   inkscape:export-filename="/home/sdomas/Projet/Blast/code/v0.2/icons/add_connection.png"
+   inkscape:export-xdpi="300"
+   inkscape:export-ydpi="300">
+  <defs
+     id="defs4">
+    <linearGradient
+       id="linearGradient5732">
+      <stop
+         style="stop-color:#000000;stop-opacity:1;"
+         offset="0"
+         id="stop5734" />
+      <stop
+         style="stop-color:#000000;stop-opacity:0.78195488;"
+         offset="1"
+         id="stop5736" />
+    </linearGradient>
+    <linearGradient
+       id="linearGradient4248">
+      <stop
+         style="stop-color:#205026;stop-opacity:1;"
+         offset="0"
+         id="stop4250" />
+      <stop
+         id="stop4256"
+         offset="1"
+         style="stop-color:#285e31;stop-opacity:0.49803922;" />
+    </linearGradient>
+  </defs>
+  <sodipodi:namedview
+     id="base"
+     pagecolor="#ffffff"
+     bordercolor="#666666"
+     borderopacity="1.0"
+     inkscape:pageopacity="0.0"
+     inkscape:pageshadow="2"
+     inkscape:zoom="11.313708"
+     inkscape:cx="34.613044"
+     inkscape:cy="13.989927"
+     inkscape:document-units="px"
+     inkscape:current-layer="layer1"
+     showgrid="true"
+     inkscape:window-width="1454"
+     inkscape:window-height="800"
+     inkscape:window-x="435"
+     inkscape:window-y="129"
+     inkscape:window-maximized="0"
+     fit-margin-top="0"
+     fit-margin-left="0"
+     fit-margin-right="0"
+     fit-margin-bottom="0"
+     borderlayer="true"
+     inkscape:showpageshadow="false">
+    <inkscape:grid
+       type="xygrid"
+       id="grid5846"
+       units="px"
+       empspacing="5"
+       visible="true"
+       enabled="true"
+       snapvisiblegridlinesonly="true"
+       spacingx="1px"
+       spacingy="1px"
+       originx="-15.46875px"
+       originy="-10.514493px" />
+  </sodipodi:namedview>
+  <metadata
+     id="metadata7">
+    <rdf:RDF>
+      <cc:Work
+         rdf:about="">
+        <dc:format>image/svg+xml</dc:format>
+        <dc:type
+           rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
+        <dc:title></dc:title>
+      </cc:Work>
+    </rdf:RDF>
+  </metadata>
+  <g
+     inkscape:label="Calque 1"
+     inkscape:groupmode="layer"
+     id="layer1"
+     transform="translate(-66.5625,-24.46875)">
+    <path
+       style="fill:#000000;fill-opacity:1;stroke:#000000;stroke-width:2;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
+       d="m 98.55045,26.08659 0,3.543307 3.5433,-1.771654 z"
+       id="path4205"
+       inkscape:connector-curvature="0" />
+    <path
+       style="fill:#000000;fill-opacity:1;stroke:#000000;stroke-width:2;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
+       d="m 67.550445,36.08659 0,3.543307 3.543305,-1.771654 z"
+       id="path4205-7"
+       inkscape:connector-curvature="0" />
+    <path
+       style="fill:none;stroke:#000000;stroke-width:2;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
+       d="m 20.543305,16.499999 15,0 0,-10.0000003 15,8e-7"
+       id="path6694"
+       inkscape:connector-curvature="0"
+       transform="translate(50.550445,21.358244)"
+       sodipodi:nodetypes="cccc" />
+    <path
+       style="color:#000000;fill:#3bb21f;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:1;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+       d="m 91.09375,32.858243 c -1.108,0 -2,0.892001 -2,2 l 0,6 -6,0 c -1.108,0 -2,0.892001 -2,2 l 0,4 c 0,1.108 0.892,2 2,2 l 6,0 0,6 c 0,1.108 0.892,2 2,2 l 4,0 c 1.108,0 2,-0.892 2,-2 l 0,-6 6,0 c 1.108,0 2,-0.892 2,-2 l 0,-4 c 0,-1.107999 -0.892,-2 -2,-2 l -6,0 0,-6 c 0,-1.107999 -0.892,-2 -2,-2 l -4,0 z"
+       id="rect4258-34"
+       inkscape:connector-curvature="0" />
+  </g>
+</svg>
diff --git a/icons/add_group.png b/icons/add_group.png
new file mode 100644 (file)
index 0000000..fd3ac9e
Binary files /dev/null and b/icons/add_group.png differ
diff --git a/icons/add_group.svg b/icons/add_group.svg
new file mode 100644 (file)
index 0000000..a0629ec
--- /dev/null
@@ -0,0 +1,177 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!-- Created with Inkscape (http://www.inkscape.org/) -->
+
+<svg
+   xmlns:dc="http://purl.org/dc/elements/1.1/"
+   xmlns:cc="http://creativecommons.org/ns#"
+   xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+   xmlns:svg="http://www.w3.org/2000/svg"
+   xmlns="http://www.w3.org/2000/svg"
+   xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+   xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+   width="49"
+   height="50.401577"
+   id="svg2"
+   version="1.1"
+   inkscape:version="0.48.5 r10040"
+   sodipodi:docname="add_group.svg"
+   inkscape:export-filename="/home/sdomas/Projet/Blast/code/v0.2/icons/add_group_select.png"
+   inkscape:export-xdpi="300.06253"
+   inkscape:export-ydpi="300.06253">
+  <defs
+     id="defs4">
+    <linearGradient
+       id="linearGradient5732">
+      <stop
+         style="stop-color:#000000;stop-opacity:1;"
+         offset="0"
+         id="stop5734" />
+      <stop
+         style="stop-color:#000000;stop-opacity:0.78195488;"
+         offset="1"
+         id="stop5736" />
+    </linearGradient>
+    <linearGradient
+       id="linearGradient4248">
+      <stop
+         style="stop-color:#205026;stop-opacity:1;"
+         offset="0"
+         id="stop4250" />
+      <stop
+         id="stop4256"
+         offset="1"
+         style="stop-color:#285e31;stop-opacity:0.49803922;" />
+    </linearGradient>
+  </defs>
+  <sodipodi:namedview
+     id="base"
+     pagecolor="#ffffff"
+     bordercolor="#666666"
+     borderopacity="1.0"
+     inkscape:pageopacity="0.0"
+     inkscape:pageshadow="2"
+     inkscape:zoom="8"
+     inkscape:cx="55.945956"
+     inkscape:cy="29.358358"
+     inkscape:document-units="px"
+     inkscape:current-layer="layer1"
+     showgrid="true"
+     inkscape:window-width="1454"
+     inkscape:window-height="800"
+     inkscape:window-x="425"
+     inkscape:window-y="32"
+     inkscape:window-maximized="0"
+     fit-margin-top="0"
+     fit-margin-left="0"
+     fit-margin-right="0"
+     fit-margin-bottom="0">
+    <inkscape:grid
+       type="xygrid"
+       id="grid5846"
+       units="px"
+       empspacing="5"
+       visible="true"
+       enabled="true"
+       snapvisiblegridlinesonly="true"
+       spacingx="1px"
+       spacingy="1px"
+       originx="-3px"
+       originy="-0.99999815px" />
+  </sodipodi:namedview>
+  <metadata
+     id="metadata7">
+    <rdf:RDF>
+      <cc:Work
+         rdf:about="">
+        <dc:format>image/svg+xml</dc:format>
+        <dc:type
+           rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
+        <dc:title></dc:title>
+      </cc:Work>
+    </rdf:RDF>
+  </metadata>
+  <g
+     inkscape:label="Calque 1"
+     inkscape:groupmode="layer"
+     id="layer1"
+     transform="translate(-54.09375,-16.456669)">
+    <rect
+       style="color:#000000;fill:none;stroke:#000000;stroke-width:2;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+       id="rect2987-5-4"
+       width="11.000002"
+       height="8.9999981"
+       x="83.09375"
+       y="37.858246" />
+    <rect
+       style="color:#000000;fill:none;stroke:#000000;stroke-width:3;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+       id="rect2987"
+       width="44.000004"
+       height="35"
+       x="55.09375"
+       y="26.858242" />
+    <rect
+       style="color:#000000;fill:#3bb21f;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:3;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+       id="rect4258"
+       width="6"
+       height="20"
+       x="90.09375"
+       y="46.858246"
+       rx="2"
+       ry="2" />
+    <rect
+       style="color:#000000;fill:#3bb21f;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:3;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+       id="rect4258-3"
+       width="6"
+       height="20"
+       x="53.858246"
+       y="-103.09375"
+       rx="2"
+       ry="2"
+       transform="matrix(0,1,-1,0,0,0)" />
+    <text
+       xml:space="preserve"
+       style="font-size:16px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:center;line-height:125%;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:middle;fill:#000000;fill-opacity:1;stroke:none;font-family:Wingdings;-inkscape-font-specification:Wingdings"
+       x="70.09375"
+       y="23.858244"
+       id="text5848"
+       sodipodi:linespacing="125%"><tspan
+         sodipodi:role="line"
+         id="tspan5850"
+         x="70.09375"
+         y="23.858244"
+         style="font-size:6px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:center;line-height:125%;writing-mode:lr-tb;text-anchor:middle;font-family:Wingdings;-inkscape-font-specification:Wingdings">group</tspan></text>
+    <rect
+       style="color:#000000;fill:none;stroke:#000000;stroke-width:3;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+       id="rect2987-2"
+       width="31.000004"
+       height="9.4015751"
+       x="55.09375"
+       y="17.456669" />
+    <rect
+       style="color:#000000;fill:none;stroke:#000000;stroke-width:2;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+       id="rect2987-5"
+       width="16.000002"
+       height="8.9999981"
+       x="60.09375"
+       y="31.858244" />
+    <path
+       style="fill:none;stroke:#000000;stroke-width:2;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;stroke-miterlimit:4;stroke-dasharray:none"
+       d="m 76.09375,35.858244 3,0 0,4 4,0"
+       id="path5925"
+       inkscape:connector-curvature="0" />
+    <rect
+       style="color:#000000;fill:none;stroke:#000000;stroke-width:2;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+       id="rect2987-5-8"
+       width="16.000002"
+       height="8.9999981"
+       x="60.09375"
+       y="46.858246" />
+    <path
+       style="fill:none;stroke:#000000;stroke-width:2;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;stroke-miterlimit:4;stroke-dasharray:none"
+       d="m 25,39 3,0 0,-8 4,0"
+       id="path5945"
+       inkscape:connector-curvature="0"
+       transform="translate(51.09375,13.858244)"
+       sodipodi:nodetypes="cccc" />
+  </g>
+</svg>
diff --git a/icons/add_group_select.png b/icons/add_group_select.png
new file mode 100644 (file)
index 0000000..d1d176c
Binary files /dev/null and b/icons/add_group_select.png differ
diff --git a/icons/add_group_select.svg b/icons/add_group_select.svg
new file mode 100644 (file)
index 0000000..06a9610
--- /dev/null
@@ -0,0 +1,163 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!-- Created with Inkscape (http://www.inkscape.org/) -->
+
+<svg
+   xmlns:dc="http://purl.org/dc/elements/1.1/"
+   xmlns:cc="http://creativecommons.org/ns#"
+   xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+   xmlns:svg="http://www.w3.org/2000/svg"
+   xmlns="http://www.w3.org/2000/svg"
+   xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+   xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+   width="51"
+   height="51.401577"
+   id="svg2"
+   version="1.1"
+   inkscape:version="0.48.5 r10040"
+   sodipodi:docname="add_group_void.svg"
+   inkscape:export-filename="/home/sdomas/Projet/Blast/code/v0.2/icons/add_group_void.png"
+   inkscape:export-xdpi="300.06253"
+   inkscape:export-ydpi="300.06253">
+  <defs
+     id="defs4">
+    <linearGradient
+       id="linearGradient5732">
+      <stop
+         style="stop-color:#000000;stop-opacity:1;"
+         offset="0"
+         id="stop5734" />
+      <stop
+         style="stop-color:#000000;stop-opacity:0.78195488;"
+         offset="1"
+         id="stop5736" />
+    </linearGradient>
+    <linearGradient
+       id="linearGradient4248">
+      <stop
+         style="stop-color:#205026;stop-opacity:1;"
+         offset="0"
+         id="stop4250" />
+      <stop
+         id="stop4256"
+         offset="1"
+         style="stop-color:#285e31;stop-opacity:0.49803922;" />
+    </linearGradient>
+  </defs>
+  <sodipodi:namedview
+     id="base"
+     pagecolor="#ffffff"
+     bordercolor="#666666"
+     borderopacity="1.0"
+     inkscape:pageopacity="0.0"
+     inkscape:pageshadow="2"
+     inkscape:zoom="8"
+     inkscape:cx="36.894824"
+     inkscape:cy="23.63185"
+     inkscape:document-units="px"
+     inkscape:current-layer="layer1"
+     showgrid="true"
+     inkscape:window-width="1454"
+     inkscape:window-height="800"
+     inkscape:window-x="425"
+     inkscape:window-y="32"
+     inkscape:window-maximized="0"
+     fit-margin-top="0"
+     fit-margin-left="0"
+     fit-margin-right="0"
+     fit-margin-bottom="0">
+    <inkscape:grid
+       type="xygrid"
+       id="grid5846"
+       units="px"
+       empspacing="5"
+       visible="true"
+       enabled="true"
+       snapvisiblegridlinesonly="true"
+       spacingx="1px"
+       spacingy="1px"
+       originx="-2.5px"
+       originy="-0.50000015px" />
+  </sodipodi:namedview>
+  <metadata
+     id="metadata7">
+    <rdf:RDF>
+      <cc:Work
+         rdf:about="">
+        <dc:format>image/svg+xml</dc:format>
+        <dc:type
+           rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
+        <dc:title></dc:title>
+      </cc:Work>
+    </rdf:RDF>
+  </metadata>
+  <g
+     inkscape:label="Calque 1"
+     inkscape:groupmode="layer"
+     id="layer1"
+     transform="translate(-53.59375,-15.956669)">
+    <rect
+       style="color:#000000;fill:none;stroke:#000000;stroke-width:2;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+       id="rect2987-5-4"
+       width="11.000002"
+       height="8.9999981"
+       x="83.09375"
+       y="37.858246" />
+    <rect
+       style="color:#000000;fill:none;stroke:#000000;stroke-width:3;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+       id="rect2987"
+       width="44.000004"
+       height="35"
+       x="55.09375"
+       y="26.858242" />
+    <text
+       xml:space="preserve"
+       style="font-size:16px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:center;line-height:125%;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:middle;fill:#000000;fill-opacity:1;stroke:none;font-family:Wingdings;-inkscape-font-specification:Wingdings"
+       x="70.09375"
+       y="23.858244"
+       id="text5848"
+       sodipodi:linespacing="125%"><tspan
+         sodipodi:role="line"
+         id="tspan5850"
+         x="70.09375"
+         y="23.858244"
+         style="font-size:6px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:center;line-height:125%;writing-mode:lr-tb;text-anchor:middle;font-family:Wingdings;-inkscape-font-specification:Wingdings">group</tspan></text>
+    <rect
+       style="color:#000000;fill:none;stroke:#000000;stroke-width:3;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+       id="rect2987-2"
+       width="31.000004"
+       height="9.4015751"
+       x="55.09375"
+       y="17.456669" />
+    <rect
+       style="color:#000000;fill:none;stroke:#000000;stroke-width:2;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+       id="rect2987-5"
+       width="16.000002"
+       height="8.9999981"
+       x="60.09375"
+       y="31.858244" />
+    <path
+       style="fill:none;stroke:#000000;stroke-width:2;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
+       d="m 76.09375,35.858244 3,0 0,4 4,0"
+       id="path5925"
+       inkscape:connector-curvature="0" />
+    <rect
+       style="color:#000000;fill:none;stroke:#000000;stroke-width:2;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+       id="rect2987-5-8"
+       width="16.000002"
+       height="8.9999981"
+       x="60.09375"
+       y="46.858246" />
+    <path
+       style="fill:none;stroke:#000000;stroke-width:2;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
+       d="m 25,39 3,0 0,-8 4,0"
+       id="path5945"
+       inkscape:connector-curvature="0"
+       transform="translate(51.09375,13.858244)"
+       sodipodi:nodetypes="cccc" />
+    <path
+       style="color:#000000;fill:#3bb21f;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:1;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+       d="m 90.09375,42.858244 c -1.108,0 -2,0.892 -2,2 l 0,6 -6,0 c -1.108,0 -2,0.892 -2,2 l 0,4 c 0,1.108 0.892,2 2,2 l 6,0 0,6 c 0,1.108 0.892,2 2,2 l 4,0 c 1.108,0 2,-0.892 2,-2 l 0,-6 6,0 c 1.108,0 2,-0.892 2,-2 l 0,-4 c 0,-1.108 -0.892,-2 -2,-2 l -6,0 0,-6 c 0,-1.108 -0.892,-2 -2,-2 l -4,0 z"
+       id="rect4258"
+       inkscape:connector-curvature="0" />
+  </g>
+</svg>
diff --git a/icons/add_group_small.png b/icons/add_group_small.png
new file mode 100644 (file)
index 0000000..823db63
Binary files /dev/null and b/icons/add_group_small.png differ
diff --git a/icons/add_group_void.png b/icons/add_group_void.png
new file mode 100644 (file)
index 0000000..9975b74
Binary files /dev/null and b/icons/add_group_void.png differ
diff --git a/icons/add_group_void.svg b/icons/add_group_void.svg
new file mode 100644 (file)
index 0000000..564b4d9
--- /dev/null
@@ -0,0 +1,130 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!-- Created with Inkscape (http://www.inkscape.org/) -->
+
+<svg
+   xmlns:dc="http://purl.org/dc/elements/1.1/"
+   xmlns:cc="http://creativecommons.org/ns#"
+   xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+   xmlns:svg="http://www.w3.org/2000/svg"
+   xmlns="http://www.w3.org/2000/svg"
+   xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+   xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+   width="51"
+   height="51.401577"
+   id="svg2"
+   version="1.1"
+   inkscape:version="0.48.5 r10040"
+   sodipodi:docname="add_group_void.svg"
+   inkscape:export-filename="/home/sdomas/Projet/Blast/code/v0.2/icons/add_group_select.png"
+   inkscape:export-xdpi="300.06253"
+   inkscape:export-ydpi="300.06253">
+  <defs
+     id="defs4">
+    <linearGradient
+       id="linearGradient5732">
+      <stop
+         style="stop-color:#000000;stop-opacity:1;"
+         offset="0"
+         id="stop5734" />
+      <stop
+         style="stop-color:#000000;stop-opacity:0.78195488;"
+         offset="1"
+         id="stop5736" />
+    </linearGradient>
+    <linearGradient
+       id="linearGradient4248">
+      <stop
+         style="stop-color:#205026;stop-opacity:1;"
+         offset="0"
+         id="stop4250" />
+      <stop
+         id="stop4256"
+         offset="1"
+         style="stop-color:#285e31;stop-opacity:0.49803922;" />
+    </linearGradient>
+  </defs>
+  <sodipodi:namedview
+     id="base"
+     pagecolor="#ffffff"
+     bordercolor="#666666"
+     borderopacity="1.0"
+     inkscape:pageopacity="0.0"
+     inkscape:pageshadow="2"
+     inkscape:zoom="8"
+     inkscape:cx="36.894824"
+     inkscape:cy="23.63185"
+     inkscape:document-units="px"
+     inkscape:current-layer="layer1"
+     showgrid="true"
+     inkscape:window-width="1454"
+     inkscape:window-height="800"
+     inkscape:window-x="425"
+     inkscape:window-y="32"
+     inkscape:window-maximized="0"
+     fit-margin-top="0"
+     fit-margin-left="0"
+     fit-margin-right="0"
+     fit-margin-bottom="0">
+    <inkscape:grid
+       type="xygrid"
+       id="grid5846"
+       units="px"
+       empspacing="5"
+       visible="true"
+       enabled="true"
+       snapvisiblegridlinesonly="true"
+       spacingx="1px"
+       spacingy="1px"
+       originx="-2.5px"
+       originy="-0.50000015px" />
+  </sodipodi:namedview>
+  <metadata
+     id="metadata7">
+    <rdf:RDF>
+      <cc:Work
+         rdf:about="">
+        <dc:format>image/svg+xml</dc:format>
+        <dc:type
+           rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
+        <dc:title></dc:title>
+      </cc:Work>
+    </rdf:RDF>
+  </metadata>
+  <g
+     inkscape:label="Calque 1"
+     inkscape:groupmode="layer"
+     id="layer1"
+     transform="translate(-53.59375,-15.956669)">
+    <rect
+       style="color:#000000;fill:none;stroke:#000000;stroke-width:3;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+       id="rect2987"
+       width="44.000004"
+       height="35"
+       x="55.09375"
+       y="26.858242" />
+    <text
+       xml:space="preserve"
+       style="font-size:16px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:center;line-height:125%;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:middle;fill:#000000;fill-opacity:1;stroke:none;font-family:Wingdings;-inkscape-font-specification:Wingdings"
+       x="70.09375"
+       y="23.858244"
+       id="text5848"
+       sodipodi:linespacing="125%"><tspan
+         sodipodi:role="line"
+         id="tspan5850"
+         x="70.09375"
+         y="23.858244"
+         style="font-size:6px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:center;line-height:125%;writing-mode:lr-tb;text-anchor:middle;font-family:Wingdings;-inkscape-font-specification:Wingdings">group</tspan></text>
+    <rect
+       style="color:#000000;fill:none;stroke:#000000;stroke-width:3;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+       id="rect2987-2"
+       width="31.000004"
+       height="9.4015751"
+       x="55.09375"
+       y="17.456669" />
+    <path
+       style="color:#000000;fill:#3bb21f;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:1;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+       d="m 90.09375,42.858244 c -1.108,0 -2,0.892 -2,2 l 0,6 -6,0 c -1.108,0 -2,0.892 -2,2 l 0,4 c 0,1.108 0.892,2 2,2 l 6,0 0,6 c 0,1.108 0.892,2 2,2 l 4,0 c 1.108,0 2,-0.892 2,-2 l 0,-6 6,0 c 1.108,0 2,-0.892 2,-2 l 0,-4 c 0,-1.108 -0.892,-2 -2,-2 l -6,0 0,-6 c 0,-1.108 -0.892,-2 -2,-2 l -4,0 z"
+       id="rect4258"
+       inkscape:connector-curvature="0" />
+  </g>
+</svg>
diff --git a/icons/copy.png b/icons/copy.png
new file mode 100644 (file)
index 0000000..d7c81da
Binary files /dev/null and b/icons/copy.png differ
diff --git a/icons/cut.png b/icons/cut.png
new file mode 100644 (file)
index 0000000..a5e87df
Binary files /dev/null and b/icons/cut.png differ
diff --git a/icons/delete.png b/icons/delete.png
new file mode 100644 (file)
index 0000000..e421cdd
Binary files /dev/null and b/icons/delete.png differ
diff --git a/icons/edit_block.png b/icons/edit_block.png
new file mode 100644 (file)
index 0000000..5dc6ff1
Binary files /dev/null and b/icons/edit_block.png differ
diff --git a/icons/folder_add_16.png b/icons/folder_add_16.png
new file mode 100644 (file)
index 0000000..213aabd
Binary files /dev/null and b/icons/folder_add_16.png differ
diff --git a/icons/inter_add.png b/icons/inter_add.png
new file mode 100644 (file)
index 0000000..7e07d26
Binary files /dev/null and b/icons/inter_add.png differ
diff --git a/icons/link.png b/icons/link.png
new file mode 100644 (file)
index 0000000..0807605
Binary files /dev/null and b/icons/link.png differ
diff --git a/icons/load.png b/icons/load.png
new file mode 100644 (file)
index 0000000..b9fbbea
Binary files /dev/null and b/icons/load.png differ
diff --git a/icons/new.ico b/icons/new.ico
new file mode 100644 (file)
index 0000000..041477f
Binary files /dev/null and b/icons/new.ico differ
diff --git a/icons/new_block.ico b/icons/new_block.ico
new file mode 100644 (file)
index 0000000..7530036
Binary files /dev/null and b/icons/new_block.ico differ
diff --git a/icons/new_block.png b/icons/new_block.png
new file mode 100644 (file)
index 0000000..1b6973c
Binary files /dev/null and b/icons/new_block.png differ
diff --git a/icons/open.png b/icons/open.png
new file mode 100644 (file)
index 0000000..c9802ff
Binary files /dev/null and b/icons/open.png differ
diff --git a/icons/paste.png b/icons/paste.png
new file mode 100644 (file)
index 0000000..71f7a18
Binary files /dev/null and b/icons/paste.png differ
diff --git a/icons/redo-icon.png b/icons/redo-icon.png
new file mode 100644 (file)
index 0000000..4fe6c7f
Binary files /dev/null and b/icons/redo-icon.png differ
diff --git a/icons/save-as.png b/icons/save-as.png
new file mode 100644 (file)
index 0000000..9d2f608
Binary files /dev/null and b/icons/save-as.png differ
diff --git a/icons/save.png b/icons/save.png
new file mode 100644 (file)
index 0000000..3d3ca4a
Binary files /dev/null and b/icons/save.png differ
diff --git a/icons/undo.png b/icons/undo.png
new file mode 100644 (file)
index 0000000..40603ed
Binary files /dev/null and b/icons/undo.png differ
diff --git a/icons/window_new.png b/icons/window_new.png
new file mode 100644 (file)
index 0000000..b41e50e
Binary files /dev/null and b/icons/window_new.png differ
diff --git a/install.sh b/install.sh
new file mode 100644 (file)
index 0000000..7449bd4
--- /dev/null
@@ -0,0 +1,38 @@
+#!/bin/sh
+
+####################################
+# blast installation script
+###################################
+
+if ! [ -f ./blast ]; then
+  echo "Impossible de trouver l'executable dans le répertoire courant. Arret"
+  exit 1
+fi
+if ! [ -d ./locales ]; then
+  echo "Impossible de trouver les fichiers de langue dans le répertoire courant. Arret"
+  exit 1
+fi
+
+if ! [ -d /usr/local/bin ]; then
+  mkdir -p /usr/local/bin 
+fi
+
+if ! [ -d /usr/local/share/blast ]; then
+  mkdir -p /usr/local/share/blast 
+else
+  rm -rf /usr/local/share/blast
+  mkdir -p /usr/local/share/blast 
+fi
+
+if [ -f /usr/local/bin/blast ]; then
+  echo "Suppression de la version actuellement installée"
+  rm -f /usr/local/bin/blast
+fi
+echo "Installation :"
+echo "binaries"
+cp blast /usr/local/bin 
+echo "locales"
+cp -r locales /usr/local/share/blast/
+echo "examples"
+cp -r examples /usr/local/share/blast/
+echo "done."
diff --git a/install.sh.in b/install.sh.in
new file mode 100644 (file)
index 0000000..040ca55
--- /dev/null
@@ -0,0 +1,38 @@
+#!/bin/sh
+
+####################################
+# @@APPNAME@@ installation script
+###################################
+
+if ! [ -f ./@@APPNAME@@ ]; then
+  echo "Impossible de trouver l'executable dans le répertoire courant. Arret"
+  exit 1
+fi
+if ! [ -d ./locales ]; then
+  echo "Impossible de trouver les fichiers de langue dans le répertoire courant. Arret"
+  exit 1
+fi
+
+if ! [ -d /usr/local/bin ]; then
+  mkdir -p /usr/local/bin 
+fi
+
+if ! [ -d /usr/local/share/@@APPNAME@@ ]; then
+  mkdir -p /usr/local/share/@@APPNAME@@ 
+else
+  rm -rf /usr/local/share/@@APPNAME@@
+  mkdir -p /usr/local/share/@@APPNAME@@ 
+fi
+
+if [ -f /usr/local/bin/@@APPNAME@@ ]; then
+  echo "Suppression de la version actuellement installée"
+  rm -f /usr/local/bin/@@APPNAME@@
+fi
+echo "Installation :"
+echo "binaries"
+cp @@APPNAME@@ /usr/local/bin 
+echo "locales"
+cp -r locales /usr/local/share/@@APPNAME@@/
+echo "examples"
+cp -r examples /usr/local/share/@@APPNAME@@/
+echo "done."
diff --git a/lib/README.txt b/lib/README.txt
new file mode 100644 (file)
index 0000000..9ca12b8
--- /dev/null
@@ -0,0 +1,119 @@
+------------------------------------
+XML description of a block model :
+------------------------------------
+
+<parameter> attributes :
+  - name : required
+  - type : required
+  - value : required if context = constant/generic, optionnal if context = wb, optional but not used if context = user/port
+  - context : required
+  - core : required if context = wb, not used for others. Possibles values : r or w. Specify if the parameter will be a register
+    that is read by the core, i.e. an input port of the core, or written by the core.
+
+<inputs>, <outputs> attributes :
+  - name : required
+  - width : required
+  - purpose : optional. Possible values : clock, reset, wb, data, ... Default value is data
+  - level : optional. Possible values : basic, top, ... Default value is basic
+  - multiplicity : optional. Possible values : *, a number. Default value is 1.
+
+<bidirs> attributes :
+  - name : required
+  - width : required
+  - purpose : optional but forced to data
+  - level : optional but forced to top
+  - multiplicity : optional. Possible values : *, a number. Default value is 1.
+  If an interface has a multiplicity > 1, the user will be able to create several
+  instances of that interface. Their default name will be the reference name
+  followed by _X, where X = 1, ..., N, and N the number of instances.
+
+  
+--------------------------------------------
+XML description of an implementation model :
+--------------------------------------------
+
+<block_impl> attributes:
+  - ref_name: the name of an XML file that contains the block model associated to this implementation. Normally, it should be unique over all available blocks.
+  - ref_id : the md5 hashsum of the xml file given in ref_name. It is used to quickly retrieve the block model in the applciation.
+
+<comments> block:
+  - all elements and their attributes are amndatory but they can be void.
+
+<libraries> block:
+  - used to generate the library and use instructions.
+  - in case of using a standard package (from work or std), only use clauses will be generated.
+
+<architecture> block:
+  - constains only the architecture part of the implementation
+  - the name of the architecture will be determined automatically from the number of existing implementations for the block model. The name will be the name of the block followed by _X, where X is the rank of the implementation found when directories are parsed to found implementations.
+
+syntax:
+
+  - @{input/output/bidir} is replaced by the "real" name in the pgrah
+    of blocks. It is because the reference name given in the reference
+    block may be changed by the user for a specific instance of that
+    block in the graph. Using @{name} will lead to do produce a VHDL
+    code with the name given by the user and not the reference name.
+
+  - @{param} is replaced by the name of the parameter as given in the reference
+    blokc, which cannot be changed by the user.
+
+  - @val{param} is replaced by the value of the parameter. This value may be
+    constant, given by user, or sometimes computed according to number of
+    instances of an interface with multiplicitiy>1.
+
+  - @eval(expression) is replaced by the result of the evaluation of th arithmetic expression.
+     This expression can use +,-,*,/,(,), numbers and values of params, i.e. @val{param} expressions.
+     BEWARE : using a generic param value in an @eval{} is inadvisable, since it breaks the principles of
+     the generic use.
+     
+  - @foreach{interface}
+      // instructions
+    @endforeach
+
+    only applicable to interfaces with multiplicity>1. Used to produce
+    a sequence of instruction X times, where X is the number of
+    interface instances created by the user. For each of those interfaces,
+    instructions will be generated. If ${interface} is used
+    within the instructions, it will be replaced by the actual evaluated interface.
+
+    Example : let val_o an output interface with multiplicity="*"
+    Supposing the user created 3 instances, leaving the two first with their default name (i.e. val_o_1 val_o_2) and the last one with name val_o_last.
+    Then, if an implementation contains :
+    @foreach{val_o}
+    signal @{val_o}_enb : std_logic;
+    @endforeach
+
+    Then the generated VHDL is :
+    signal val_o_1_enb : std_logic;
+    signal val_o_2_enb : std_logic;
+    signal val_o_last_enb : std_logic;
+
+  - @caseeach{interface,signal,cases}
+      // instructions
+    @endcaseeach
+
+    similar to foreach but to produce a case statement. signal is the
+    signal used to test against the cases. Obviously, there should be
+    as much cases as the number of interface instances. If not, the
+    generation will not be complete.
+    cases may be a predefined variables (see below) or a list of values.
+
+    Example : with the same assumptions as in foreach example,
+    
+    @caseeach(val_o,sel_s,@#:1)
+      @{val_o}_enb <= '1';
+    @endcaseeach
+
+    will produce
+    case sel_s is
+       when 1 => val_o_1_enb <= '1';
+       when 2 => val_o_2_enb <= '1';
+       when 3 => val_o_last_enb <= '1';
+    end case;
+
+  - @#[-]:number : only usefull within foreach, caseeach, ... Produces an output
+    that starts at number and increments or decrements (with #-) at each case.
+
+    Example : @#-:3 will produce 3, 2, 1, 0, -1, ...
+    
diff --git a/lib/implementations/apf27-wb-master_impl.xml b/lib/implementations/apf27-wb-master_impl.xml
new file mode 100644 (file)
index 0000000..7970abf
--- /dev/null
@@ -0,0 +1,69 @@
+<?xml version="1.0" encoding="UTF-8" standalone="yes" ?>
+<block_impl ref_name="apf27-wb-master.xml" ref_md5="">
+  <comments>
+    <author firstname="stephane" lastname="Domas" mail="sdomas@univ-fcomte.fr" />
+    <date creation="2015/04/27" />
+    <related_files list="interconn.vhd,clkrstgen.vhd"/>
+    <description>
+      This component is an interface between i.MX signals
+      and the interconnector component.
+    </description>
+    <notes>
+   On i.MX&lt;->FPGA connection : the WEIM part of i.MX has a 16 bits bus address
+   but only [1:12] bits are connected to FPGA pins. From the i.MX point of view
+   it means that reading in memory mapped address 0x0002 or 0x0003 gives the same
+   result since the LSB bit of the address is not transmited.
+   
+   These 12 bits are forwarded to the interconnector which is responsible to
+   determine for what IP the data and addr signals must be routed.
+
+    </notes>
+  </comments>
+
+  <libraries>
+    <library name="IEEE">
+      <package name="std_logic_1164" use="all"/>
+      <package name="numeric_std" use="all"/>
+    </library>
+  </libraries>
+
+  <architecture>
+
+  signal write      : std_logic;
+  signal read       : std_logic;
+  signal strobe     : std_logic;
+  signal writedata  : std_logic_vector(@{wb_data_width}-1 downto 0);
+  signal address    : std_logic_vector(@{wb_addr_width}-1 downto 0);
+
+begin
+
+-- ----------------------------------------------------------------------------
+--  External signals synchronization process
+-- ----------------------------------------------------------------------------
+  process(@{clk}, @{reset})
+  begin
+    if(@{reset}='1') then
+      write     &lt;= '0';
+      read      &lt;= '0';
+      strobe    &lt;= '0';
+      writedata &lt;= (others => '0');
+      address   &lt;= (others => '0');
+    elsif(rising_edge(@{clk})) then
+      strobe    &lt;= not (@{imx_cs_n}) and not(@{imx_oe_n} and @{imx_eb3_n});
+      write     &lt;= not (@{imx_cs_n} or @{imx_eb3_n});
+      read      &lt;= not (@{imx_cs_n} or @{imx_oe_n});
+      address   &lt;= @{imx_addr};
+      writedata &lt;= @{imx_data};
+    end if;
+  end process;
+
+  @{addr_o}   &lt;= address when (strobe = '1') else (others => '0');
+  @{dat_o}    &lt;= writedata when (write = '1') else (others => '0');
+  @{stb_o}    &lt;= strobe;
+  @{we_o}     &lt;= write;
+  @{cyc_o}    &lt;= strobe;
+
+  @{imx_data} &lt;= @{dat_i} when(read = '1' ) else (others => 'Z');
+  
+  </architecture>
+</block_impl>
diff --git a/lib/implementations/demux_impl.xml b/lib/implementations/demux_impl.xml
new file mode 100644 (file)
index 0000000..bcb7ea8
--- /dev/null
@@ -0,0 +1,71 @@
+<?xml version="1.0" encoding="UTF-8" standalone="yes" ?>
+<block_impl ref_name="demux.xml" ref_md5="">
+  <comments>
+    <author firstname="stephane" lastname="Domas" mail="sdomas@univ-fcomte.fr" />
+    <date creation="2015/04/27" />
+    <related_files list=""/>
+    <description>
+      This component is a synchronous demultiplixer with variable number of outputs
+    </description>
+    <notes>
+      No notes
+    </notes>
+  </comments>
+
+  <libraries>
+    <library name="IEEE">
+      <package name="std_logic_1164" use="all"/>
+      <package name="numeric_std" use="all"/>
+    </library>
+  </libraries>
+
+  <architecture>
+
+    signal sel_s      : unsigned(@eval{@val{sel_width}-1} downto 0);
+    signal val_i_dly  : std_logic_vector(@eval{@val{val_width}-1} downto 0};
+    
+    @foreach{val_o}
+    signal @{val_o}_enb : std_logic;
+    @endforeach
+    
+    begin
+    
+    sel_s &lt;= @{sel_i};
+    
+    delay_input : process(@{clk}, @{rst})
+    begin
+    if(@{rst}='1') then
+      val_i_dly &lt;= (others => '0');
+    elsif(rising_edge(@{clk})) then
+      val_i_dly &lt;= @{val_i};
+    end if;
+    end process delay_input;
+
+    
+    demux : process(@{clk}, @{rst})
+    begin
+    if(@{rst}='1') then
+    
+      @foreach{val_o}
+      @{val_o}_enb &lt;= '0';
+      @endforeach
+
+      elsif(rising_edge(@{clk})) then
+      
+      @foreach{val_o}
+      @{val_o}_enb &lt;= '0';
+      @endforeach
+      
+      @caseeach{val_o,sel_s,@#:1}
+      @{val_o}_enb &lt;= '1';
+      @endcaseeach
+      
+      end if;
+    end process demux;
+    
+    @foreach{val_o}
+    @{val_o}   &lt;= val_i_dly when (@{val_o}_enb = '1') else (others => '0');
+    @endforeach
+    
+  </architecture>
+</block_impl>
diff --git a/lib/implementations/impls.bmf b/lib/implementations/impls.bmf
new file mode 100644 (file)
index 0000000..b544d25
Binary files /dev/null and b/lib/implementations/impls.bmf differ
diff --git a/lib/implementations/multadd.vhd b/lib/implementations/multadd.vhd
new file mode 100644 (file)
index 0000000..394b223
--- /dev/null
@@ -0,0 +1,76 @@
+-------------------------------------------------------------------------------
+--
+--  File          : multadd.vhd
+--  Related files : 
+--
+--  Author(s)     : stephane Domas (sdomas@univ-fcomte.fr)
+--
+--  Creation Date : 2015/04/27
+--
+--  Description   : This component is a multadd
+--
+--  Note          : No notes
+--
+-------------------------------------------------------------------------------
+
+library IEEE;
+use IEEE.std_logic_1164.all;
+use IEEE.numeric_std.all;
+
+entity multadd is
+  generic (
+    wb_data_width : integer := 16;
+    wb_addr_width : integer := 12
+    );
+  port (
+    -- clk/rst from multadd wrapper
+    rst : in std_logic;
+    clk : in std_logic;
+
+    -- registers r/w via wishbone
+    wb_do_op : in  std_logic;
+    wb_c     : in  std_logic_vector(wb_data_width-1 downto 0);
+    wb_d     : out std_logic_vector(2*wb_data_width-1 downto 0);
+
+    -- data ports
+    val1_i : in  std_logic_vector(17 downto 0);
+    val2_i : in  std_logic_vector(17 downto 0);
+    res_o  : out std_logic_vector(35 downto 0)
+    );
+end multadd;
+
+
+architecture multadd_1 of multadd is
+
+  -- Signals
+  signal a_s    : signed(17 downto 0);
+  signal b_s    : signed(17 downto 0);
+  signal c_s    : signed(35 downto 0);
+  signal result : signed(35 downto 0);
+
+begin
+
+  a_s <= signed(val1_i);
+  b_s <= signed(val2_i);
+  c_s <= resize(signed(wb_c), 36);
+
+  do_mult_process : process (clk, rst)
+  begin
+    if rst = '1' then
+
+      result <= to_signed(0, 36);
+
+    elsif (rising_edge(clk)) then
+
+      if wb_do_op = '1' then
+        result <= a_s * b_s + c_s;
+      end if;
+
+    end if;
+  end process do_mult_process;
+
+  res_o <= std_logic_vector(result);
+  wb_d  <= std_logic_vector(resize(result, 2*wb_data_width));
+
+end multadd_1;
+
diff --git a/lib/implementations/multadd_core.vhd b/lib/implementations/multadd_core.vhd
new file mode 100644 (file)
index 0000000..0f42489
--- /dev/null
@@ -0,0 +1,76 @@
+-------------------------------------------------------------------------------
+--
+--  File          : multadd_core.vhd
+--  Related files : 
+--
+--  Author(s)     : stephane Domas (sdomas@univ-fcomte.fr)
+--
+--  Creation Date : 2015/04/27
+--
+--  Description   : This component is a multadd
+--
+--  Note          : No notes
+--
+-------------------------------------------------------------------------------
+
+library IEEE;
+use IEEE.std_logic_1164.all;
+use IEEE.numeric_std.all;
+
+entity multadd_core is
+  generic (
+    wb_data_width : integer := 16;
+    wb_addr_width : integer := 12
+    );
+  port (
+    -- clk/rst from multadd wrapper
+    rst : in std_logic;
+    clk : in std_logic;
+
+    -- registers r/w via wishbone
+    wb_do_op : in  std_logic;
+    wb_c     : in  std_logic_vector(wb_data_width-1 downto 0);
+    wb_d     : out std_logic_vector(2*wb_data_width-1 downto 0);
+
+    -- data ports
+    val1_i : in  std_logic_vector(17 downto 0);
+    val2_i : in  std_logic_vector(17 downto 0);
+    res_o : out std_logic_vector(35 downto 0)
+    );
+end multadd_core;
+
+
+architecture multadd_core_1 of multadd_core is
+
+     -- Signals
+  signal a_s      : signed(17 downto 0);
+  signal b_s      : signed(17 downto 0);
+  signal c_s      : signed(35 downto 0);
+  signal result   : signed(35 downto 0);
+
+begin
+
+  a_s <= signed(val1_i);
+  b_s <= signed(val2_i);
+  c_s <= resize(signed(wb_c),36);
+  
+  do_mult_process : process (clk, rst)
+  begin
+    if rst = '1' then
+      
+      result <= to_signed(0,36);
+      
+    elsif (rising_edge(clk)) then
+
+      if wb_do_op = '1' then
+        result <= a_s * b_s + c_s;
+      end if;
+      
+    end if;
+  end process do_mult_process;
+
+  res_o <= std_logic_vector(result);
+  wb_d <= std_logic_vector(resize(result,32);
+  
+end multadd_core_1;
+
diff --git a/lib/implementations/multadd_ctrl.vhd b/lib/implementations/multadd_ctrl.vhd
new file mode 100644 (file)
index 0000000..b02bd3d
--- /dev/null
@@ -0,0 +1,154 @@
+-------------------------------------------------------------------------------
+--
+--  File          : multadd_ctrl.vhd
+--  Related files : multadd.vhd
+--
+--  Author(s)     : stephane Domas (sdomas@univ-fcomte.fr)
+--
+--  Creation Date : 2015/04/27
+--
+--  Description   : This component is generated automatically.
+--                  It contains processes to r/w registers defined for multadd
+--                  via wishbone.
+--
+--  Note          : No notes
+--
+-------------------------------------------------------------------------------
+
+library IEEE;
+use IEEE.std_logic_1164.all;
+use IEEE.numeric_std.all;
+
+-------------------------------------------------------------------------------
+--  wishbone registers
+-------------------------------------------------------------------------------
+--  name               bits            address  R/W         
+--  wb_do_op           0               0x0000    W
+--  wb_c               (15 downto 0)   0x0001    W
+--  wb_d               (15 downto 0)   0x0002    R
+--  wb_d               (31 downto 0)   0x0003    R
+--
+-------------------------------------------------------------------------------
+
+entity multadd_ctrl is
+  generic (
+    wb_data_width : integer := 16;
+    wb_addr_width : integer := 2
+    );
+  port (
+    -- clk/rst from interconnector
+    rst : in std_logic;
+    clk : in std_logic;
+
+    -- addr/data from interconnector
+    addr_i : in  std_logic_vector(wb_addr_width-1 downto 0);
+    dat_i  : in  std_logic_vector(wb_data_width-1 downto 0);
+    dat_o  : out std_logic_vector(wb_data_width-1 downto 0);
+    cyc_i  : in  std_logic;
+    stb_i  : in  std_logic;
+    we_i   : in  std_logic;
+    ack_o  : out std_logic;
+
+    -- registers r/w via wishbone that are forwarded to the block
+    wb_do_op : out  std_logic;
+    wb_c     : out  std_logic_vector(wb_data_width-1 downto 0);
+    wb_d     : in std_logic_vector(2*wb_data_width-1 downto 0)
+
+    );
+end multadd_ctrl;
+
+
+architecture multadd_ctrl1 of multadd_ctrl is
+
+  -- signals : registers r/w via wishbone
+  signal wb_do_op_s : std_logic;
+  signal wb_c_s     : std_logic_vector(wb_data_width-1 downto 0);
+  signal wb_d_s     : std_logic_vector(2*wb_data_width-1 downto 0);
+
+  -- signals : wishbone related
+  signal read_data : std_logic_vector(wb_data_width-1 downto 0);
+  signal read_ack  : std_logic;
+  signal write_ack : std_logic;
+  signal write_rise : std_logic;
+
+begin
+-- ----------------------------------------------------------------------------
+--  signals from/to ports
+-- ----------------------------------------------------------------------------
+  wb_d_s <= wb_d;
+  wb_c <= wb_c_s;
+  wb_do_op <= wb_do_op_s;
+  
+-- ----------------------------------------------------------------------------
+--  write rising edge detection
+-- ----------------------------------------------------------------------------
+  detection_front : process(gls_clk, gls_reset)
+    variable signal_old : std_logic;
+  begin
+    if (gls_reset = '1') then
+      signal_old := '0';
+      write_rise <= '0';
+    elsif rising_edge(gls_clk) then
+      if (signal_old = '0' and stb_i = '1' and cyc_i = '1' and we_i = '1') then
+        write_rise <= '1';
+      else
+        write_rise <= '0';
+      end if;
+      signal_old := we_i;
+    end if;
+  end process detection_front;
+
+-- ----------------------------------------------------------------------------
+--  Register reading process
+-- ----------------------------------------------------------------------------
+  reading_reg : process(clk, rst)
+  begin
+    if(rst = '1') then
+      read_ack  <= '0';
+      read_data <= (others => '0');
+    elsif(rising_edge(clk)) then
+      read_ack <= '0';
+      if (stb_i = '1' and cyc_i = '1' and we_i = '0') then
+        read_ack <= '1';
+        if(addr_i = "10") then
+          read_data <= wb_d_s(15 downto 0);
+        elsif(addr_i = "11") then
+          read_data <= wb_d_s(31 downto 16);
+        else
+          read_data <= (others => '0');
+        end if;
+      end if;
+    end if;
+  end process reading_reg;
+
+-- ----------------------------------------------------------------------------
+--  Register writing process
+-- ----------------------------------------------------------------------------
+  writing_reg : process(clk, rst)
+  begin
+    if(rst = '1') then
+      write_ack <= '0';
+      wb_do_op_s  <= '0';
+      wb_c_s      <= (others => '0');
+    elsif(rising_edge(clk)) then
+      write_ack <= '0';
+      wb_do_op_s  <= '0';
+      if (write_rise = '1') then
+        write_ack <= '1';
+        if (addr_i = "00") then
+          wb_do_op_s <= '1';
+        elsif (addr_i = "01") then
+          wb_c_s <= dat_i;
+        end if;
+      end if;
+    end if;
+  end process writing_reg;
+
+-- ----------------------------------------------------------------------------
+-- assignations for wishbone outputs
+-- ----------------------------------------------------------------------------
+  ack_o <= read_ack or write_ack;
+  dat_o <= read_data when (stb_i = '1' and cyc_i = '1' and we_i = '0') else (others => '0');
+
+end multadd_ctrl1;
+
diff --git a/lib/implementations/multadd_impl.xml b/lib/implementations/multadd_impl.xml
new file mode 100644 (file)
index 0000000..fc2d10f
--- /dev/null
@@ -0,0 +1,63 @@
+<?xml version="1.0" encoding="UTF-8" standalone="yes" ?>\r
+<block_impl ref_name="multadd.xml" ref_md5="">\r
+  <comments>\r
+    <author firstname="stephane" lastname="Domas" mail="sdomas@univ-fcomte.fr" />\r
+    <date creation="2015/04/27" />\r
+    <related_files list=""/>\r
+    <description>\r
+      This component is a multadd\r
+    </description>\r
+    <notes>\r
+      No notes\r
+    </notes>\r
+  </comments>\r
+\r
+  <libraries>\r
+    <library name="IEEE">\r
+      <package name="std_logic_1164" use="all"/>\r
+      <package name="numeric_std" use="all"/>\r
+    </library>\r
+  </libraries>\r
+\r
+  <architecture>\r
+\r
+   -- Signals\r
+  signal a_s      : signed(@eval{@val{in_width}-1} downto 0);\r
+  signal b_s      : signed(@eval{@val{in_width}-1} downto 0);\r
+  signal c_s      : signed(@eval{2*@val{in_width}-1} downto 0);\r
+  signal result   : signed(@eval{2*@val{in_width}-1} downto 0);\r
+\r
+begin\r
+\r
+  a_s &lt;= signed(@{a});\r
+  b_s &lt;= signed(@{b});\r
+  c_s &lt;= resize(signed(@{wb_c}),@eval{2*@val{in_width}});\r
+  \r
+  do_mult_process : process (@{clk}, @{rst})\r
+  begin\r
+    if @{rst} = '1' then\r
+      \r
+      result &lt;= to_signed(0,@eval{2*@val{in_width});\r
+      \r
+    elsif (rising_edge(@{clk})) then\r
+\r
+      if @{wb_do_op} = '1' then\r
+        result &lt;= a_s * b_s + c_s;\r
+      end if;\r
+      \r
+    end if;\r
+  end process do_mult_process;\r
+\r
+  @{d} &lt;= std_logic_vector(result);\r
+  @{wb_d} &lt;= std_logic_vector(resize(result,2*wb_data_width));\r
+  \r
+  </architecture>\r
+\r
+  <patterns>\r
+    <parameters>\r
+      <parameter name="m" value="1" />\r
+    </parameters>    \r
+    <delta value="1" />\r
+  </patterns>\r
+  \r
+</block_impl>\r
diff --git a/lib/references/apf27-wb-master.xml b/lib/references/apf27-wb-master.xml
new file mode 100644 (file)
index 0000000..82ee08a
--- /dev/null
@@ -0,0 +1,46 @@
+<?xml version="1.0" encoding="UTF-8" standalone="yes" ?>
+<block>
+  <informations>
+    <name>
+      wishbone master for apf27
+    </name>
+    <category ids="1,4" />  
+    <description>
+      <brief>
+       This block is the wishbone master of the design, connected to the i.MX of APF27
+      </brief>
+      <detailed>
+       This block is the wishbone master of the design, connected to the i.MX of APF27
+      </detailed>     
+    </description>    
+  </informations>
+
+  <parameters>
+  </parameters>
+
+  <interfaces>
+    <inputs>
+      <input name="clk" type="boolean" width="1" purpose="clock" />
+      <input name="rst" type="boolean" width="1" purpose="reset" />
+      
+      <input name="imx_addr" type="expression" width="$wb_addr_width" level="top"/>
+      <input name="imx_cs_n" type="boolean" width="1" level="top"/>
+      <input name="imx_oe_n" type="boolean" width="1" level="top"/>
+      <input name="imx_eb3_n" type="boolean" width="1" level="top"/>
+      
+      <input name="ack_i" type="boolean" width="1" purpose="wb" />
+      <input name="dat_i" width="$wb_data_width" purpose="wb" />
+    </inputs>
+    <outputs>
+      <output name="addr_o" type="expression" width="$wb_addr_width" purpose="wb" />
+      <output name="dat_o" type="expression" width="$wb_data_width" purpose="wb" />      
+      <output name="cyc_o" type="boolean" width="1" purpose="wb" />
+      <output name="stb_o" type="boolean" width="1" purpose="wb" />
+      <output name="we_o" type="boolean" width="1" purpose="wb" />
+    </outputs>
+    <bidirs>
+      <bidir name="imx_data" width="$wb_data_width" level="top"/>
+    </bidirs>
+  </interfaces>
+
+</block>
diff --git a/lib/references/demux.xml b/lib/references/demux.xml
new file mode 100644 (file)
index 0000000..cd66442
--- /dev/null
@@ -0,0 +1,36 @@
+<?xml version="1.0" encoding="UTF-8" standalone="yes" ?>\r
+<block>\r
+  <informations>\r
+    <name>\r
+      block demultiplexer\r
+    </name>\r
+    <category ids="1,4" />  \r
+    <description>\r
+      <brief>\r
+       This block demux an entry presented on FPGA pins over a variable number of outputs\r
+      </brief>\r
+      <detailed>\r
+       This block demux an entry presented on FPGA pins over a variable number of outputs\r
+      </detailed>     \r
+    </description>    \r
+  </informations>\r
+\r
+  <parameters>\r
+    <parameter name="val_width" type="string" value="0" context="user"/>\r
+    <parameter name="sel_width" type="expression" value="$if_nb" iface="val_o" context="port"/>\r
+  </parameters>\r
+\r
+  <interfaces>\r
+    <inputs>\r
+      <input name="clk" type="boolean" width="1" purpose="clock" />\r
+      <input name="rst" type="boolean" width="1" purpose="reset" />\r
+      \r
+      <input name="val_i" type="expression" width="$val_width" level="top"/>\r
+      <input name="sel_i" type="expression" width="$sel_width" />\r
+    </inputs>\r
+    <outputs>\r
+      <output name="val_o" type="expression" width="$val_width" multiplicity="*"/>\r
+    </outputs>    \r
+  </interfaces>\r
+\r
+</block>\r
diff --git a/lib/references/multadd.xml b/lib/references/multadd.xml
new file mode 100644 (file)
index 0000000..7ef16bd
--- /dev/null
@@ -0,0 +1,43 @@
+<?xml version="1.0" encoding="UTF-8" standalone="yes" ?>\r
+<block>\r
+  <informations>\r
+    <name>\r
+      block multiply/add\r
+    </name>\r
+    <category ids="2,5" />  \r
+    <description>\r
+      <brief>\r
+       This block multiplies 2 input values, adding the result to a third one.\r
+      </brief>\r
+      <detailed>\r
+       This block does d=a*b+c.\r
+       a/b are provided by input port.\r
+       c is set via the wishbone interconnector\r
+       d is forwarded to an output port and can be retrieved via the wishbone interconnector\r
+      </detailed>     \r
+    </description>    \r
+  </informations>\r
+\r
+  <parameters>\r
+    \r
+    <parameter name="wb_c" type="expression" width="$wb_data_width" value="0" context="wb" wishbone="w,data,perm"/>\r
+    <parameter name="wb_d" type="expression" width="2*$wb_data_width" value="0" context="wb" wishbone="r"/>\r
+    <parameter name="wb_do_op" type="boolean" width="1" value="false" context="wb" wishbone="w,true,trigger"/>\r
+    \r
+    <parameter name="in_width" type="string" value="10" context="user"/>\r
+    \r
+  </parameters>\r
+\r
+  <interfaces>\r
+    <inputs>\r
+      <input name="clk" type="boolean" width="1" purpose="clock" />\r
+      <input name="rst" type="boolean" width="1" purpose="reset" />\r
+      <input name="a" type="expression" width="$in_width" />\r
+      <input name="b" type="expression" width="$in_width" />\r
+      \r
+    </inputs>\r
+    <outputs>\r
+      <output name="d" type="expression" width="2*$in_width" />\r
+    </outputs>    \r
+  </interfaces>\r
+</block>\r
diff --git a/lib/references/references.bmf b/lib/references/references.bmf
new file mode 100644 (file)
index 0000000..6685627
Binary files /dev/null and b/lib/references/references.bmf differ
diff --git a/object-files.txt b/object-files.txt
new file mode 100644 (file)
index 0000000..841a369
--- /dev/null
@@ -0,0 +1,47 @@
+COMMON-OBJ = $(BUILDPATH)/AbstractBlock.o \
+          $(BUILDPATH)/FunctionalBlock.o \
+          $(BUILDPATH)/ReferenceBlock.o \
+          $(BUILDPATH)/GroupBlock.o \
+           $(BUILDPATH)/AbstractInterface.o \
+          $(BUILDPATH)/ConnectedInterface.o \
+          $(BUILDPATH)/FunctionalInterface.o \
+          $(BUILDPATH)/GroupInterface.o \
+          $(BUILDPATH)/ReferenceInterface.o \
+          $(BUILDPATH)/BlockImplementation.o \
+          $(BUILDPATH)/Graph.o \
+          $(BUILDPATH)/AbstractBoxItem.o \
+          $(BUILDPATH)/BoxItem.o \
+          $(BUILDPATH)/GroupItem.o \
+          $(BUILDPATH)/BlockCategory.o \
+          $(BUILDPATH)/BlockLibraryTree.o \
+          $(BUILDPATH)/BlockLibraryWidget.o \
+          $(BUILDPATH)/moc_BlockLibraryWidget.o \
+          $(BUILDPATH)/BlockParameter.o \
+          $(BUILDPATH)/BlockParameterUser.o \
+          $(BUILDPATH)/BlockParameterGeneric.o \
+          $(BUILDPATH)/BlockParameterPort.o \
+          $(BUILDPATH)/BlockParameterWishbone.o \
+          $(BUILDPATH)/ConnectionItem.o \
+          $(BUILDPATH)/Dispatcher.o \
+          $(BUILDPATH)/Exception.o \
+          $(BUILDPATH)/Graph.o \
+          $(BUILDPATH)/GroupScene.o \
+          $(BUILDPATH)/InterfaceItem.o \
+          $(BUILDPATH)/MainWindow.o \
+          $(BUILDPATH)/moc_MainWindow.o \
+          $(BUILDPATH)/ArithmeticEvaluator.o \
+          $(BUILDPATH)/moc_ArithmeticEvaluator.o \
+          $(BUILDPATH)/BlockWidget.o \
+          $(BUILDPATH)/moc_BlockWidget.o \
+          $(BUILDPATH)/GroupWidget.o \
+          $(BUILDPATH)/moc_GroupWidget.o \
+          $(BUILDPATH)/Parameters.o \
+          $(BUILDPATH)/moc_Parameters.o \
+           $(BUILDPATH)/rcc_blast.o \
+           $(BUILDPATH)/BlocksToConfigureWidget.o \
+           $(BUILDPATH)/moc_BlocksToConfigureWidget.o \
+           $(BUILDPATH)/ParametersWindow.o \
+           $(BUILDPATH)/moc_ParametersWindow.o \
+           $(BUILDPATH)/InterfacePropertiesWindow.o \
+           $(BUILDPATH)/moc_InterfacePropertiesWindow.o \
+           $(BUILDPATH)/blast.o
diff --git a/projectfile.xsd b/projectfile.xsd
new file mode 100644 (file)
index 0000000..36fe54e
--- /dev/null
@@ -0,0 +1,333 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema">
+
+
+    <!-- déclaration des groupes d'attributs -->
+
+    <xs:attributeGroup name="group_itemAttrGroup">
+       <xs:attribute ref="id"/>
+       <xs:attribute ref="name"/>
+       <xs:attribute ref="upper_group"/>
+       <xs:attribute ref="upper_item"/>
+       <xs:attribute ref="position"/>
+       <xs:attribute ref="dimension"/>
+    </xs:attributeGroup>
+
+    <xs:attributeGroup name="group_ifaceAttrGroup">
+       <xs:attribute ref="id"/>
+       <xs:attribute ref="name"/>
+       <xs:attribute ref="level"/>
+       <xs:attribute ref="direction"/>
+       <xs:attribute ref="orientation"/>
+       <xs:attribute ref="position"/>
+    </xs:attributeGroup>
+
+    <xs:attributeGroup name="block_itemsAttrGroup">
+       <xs:attribute ref="functional_count" />
+       <xs:attribute ref="group_count" />
+    </xs:attributeGroup>
+
+    <xs:attributeGroup name="bi_functionalAttrGroup">
+       <xs:attribute ref="id" />
+       <xs:attribute ref="ref_xml" />
+       <xs:attribute ref="ref_md5" />
+       <xs:attribute ref="name" />
+       <xs:attribute ref="position" />
+       <xs:attribute ref="dimension" />
+    </xs:attributeGroup>
+
+    <xs:attributeGroup name="bif_parameterAttrGroup">
+       <xs:attribute ref="name" />
+       <xs:attribute ref="value" />
+       <xs:attribute ref="context" />
+       <xs:attribute ref="type" />
+
+    </xs:attributeGroup>
+
+    <xs:attributeGroup name="bif_ifaceAttrGroup">
+       <xs:attribute ref="id" />
+       <xs:attribute ref="name" />
+       <xs:attribute ref="ref_name" />
+       <xs:attribute ref="orientation" />
+       <xs:attribute ref="position" />
+    </xs:attributeGroup>
+
+    <xs:attributeGroup name="bi_groupAttrGroup">
+       <xs:attribute ref="id" />
+       <xs:attribute ref="inside_group" />
+       <xs:attribute ref="position" />
+       <xs:attribute ref="dimension" />
+    </xs:attributeGroup>
+
+    <xs:attributeGroup name="big_ifaceAttrGroup">
+       <xs:attribute ref="id" />
+       <xs:attribute ref="ref_name" />
+       <xs:attribute ref="orientation" />
+       <xs:attribute ref="position" />
+    </xs:attributeGroup>
+
+    <xs:attributeGroup name="connectionAttrGroup">
+       <xs:attribute ref="from" />
+       <xs:attribute ref="to" />
+    </xs:attributeGroup>
+
+
+    <!-- déclaration des attributs -->
+
+    <xs:attribute name="count">
+       <xs:simpleType>
+           <xs:restriction base="xs:nonNegativeInteger">
+               <xs:minInclusive value="0"/>
+           </xs:restriction>
+       </xs:simpleType>
+    </xs:attribute>
+
+    <xs:attribute name="id">
+       <xs:simpleType>
+           <xs:restriction base="xs:nonNegativeInteger">
+               <xs:minInclusive value="0"/>
+           </xs:restriction>
+       </xs:simpleType>
+    </xs:attribute>
+
+    <xs:attribute name="upper_group">
+       <xs:simpleType>
+           <xs:restriction base="xs:integer">
+               <xs:minInclusive value="-1"/>
+           </xs:restriction>
+       </xs:simpleType>
+    </xs:attribute>
+
+    <xs:attribute name="upper_item">
+       <xs:simpleType>
+           <xs:restriction base="xs:integer">
+               <xs:minInclusive value="-1"/>
+           </xs:restriction>
+       </xs:simpleType>
+    </xs:attribute>
+
+    <xs:attribute name="inside_group">
+       <xs:simpleType>
+           <xs:restriction base="xs:nonNegativeInteger">
+               <xs:minInclusive value="0"/>
+           </xs:restriction>
+       </xs:simpleType>
+    </xs:attribute>
+
+    <xs:attribute name="functional_count">
+       <xs:simpleType>
+           <xs:restriction base="xs:nonNegativeInteger">
+               <xs:minInclusive value="0"/>
+           </xs:restriction>
+       </xs:simpleType>
+    </xs:attribute>
+
+    <xs:attribute name="group_count">
+       <xs:simpleType>
+           <xs:restriction base="xs:nonNegativeInteger">
+               <xs:minInclusive value="0"/>
+           </xs:restriction>
+       </xs:simpleType>
+    </xs:attribute>
+
+    <xs:attribute name="value">
+       <xs:simpleType>
+           <xs:restriction base="xs:nonNegativeInteger">
+               <xs:minInclusive value="0"/>
+           </xs:restriction>
+       </xs:simpleType>
+    </xs:attribute>
+
+    <xs:attribute name="from">
+       <xs:simpleType>
+           <xs:restriction base="xs:nonNegativeInteger">
+               <xs:minInclusive value="0"/>
+           </xs:restriction>
+       </xs:simpleType>
+    </xs:attribute>
+
+    <xs:attribute name="to">
+       <xs:simpleType>
+           <xs:restriction base="xs:nonNegativeInteger">
+               <xs:minInclusive value="0"/>
+           </xs:restriction>
+       </xs:simpleType>
+    </xs:attribute>
+
+    <xs:attribute name="position" type="xs:string"/>
+    <xs:attribute name="dimension" type="xs:string"/>
+    <xs:attribute name="level" type="xs:string"/>
+    <xs:attribute name="direction" type="xs:string"/>
+    <xs:attribute name="orientation" type="xs:string"/>
+    <xs:attribute name="name" type="xs:string"/>
+    <xs:attribute name="ref_name" type="xs:string"/>
+    <xs:attribute name="ref_xml" type="xs:string"/>
+    <xs:attribute name="ref_md5" type="xs:string"/>
+    <xs:attribute name="context" type="xs:string"/>
+    <xs:attribute name="type" type="xs:string"/>
+
+
+    <!-- déclaration des groupes d'éléments -->
+
+    <xs:group name="rootElmtGroup">
+       <xs:sequence>
+           <xs:element ref="scenes"/>
+           <xs:element ref="connections"/>     
+       </xs:sequence>
+    </xs:group>
+
+    <xs:group name="sceneElmtGroup">
+       <xs:sequence>
+           <xs:element ref="group_item"/>
+           <xs:element ref="block_items"/>
+       </xs:sequence>
+    </xs:group>
+
+    <xs:group name="block_itemsElmtGroup">
+       <xs:sequence>
+           <xs:element ref="bi_functional" minOccurs="0" maxOccurs="unbounded"/>
+           <xs:element ref="bi_group" minOccurs="0"/>
+       </xs:sequence>
+    </xs:group>
+
+    <xs:group name="bi_functionalElmtGroup">
+       <xs:sequence>
+           <xs:element ref="bif_parameters"/>
+           <xs:element ref="bif_ifaces"/>
+       </xs:sequence>
+    </xs:group>
+
+
+    <!-- déclaration des éléments -->
+
+    <xs:element name="scenes">
+       <xs:complexType>
+           <xs:sequence>
+               <xs:element ref="scene" maxOccurs="unbounded" />
+           </xs:sequence>
+           <xs:attribute ref="count"/>
+       </xs:complexType>
+    </xs:element>
+
+    <xs:element name="scene">
+       <xs:complexType>
+           <xs:group ref="sceneElmtGroup"/>
+           <xs:attribute ref="id"/>
+       </xs:complexType>
+    </xs:element>
+
+    <xs:element name="group_item">
+       <xs:complexType>
+           <xs:sequence>
+               <xs:element ref="group_ifaces" maxOccurs="unbounded" />
+           </xs:sequence>      
+           <xs:attributeGroup ref="group_itemAttrGroup"/>
+       </xs:complexType>
+    </xs:element>
+
+    <xs:element name="group_ifaces">
+       <xs:complexType>
+           <xs:sequence>
+               <xs:element ref="group_iface" minOccurs="0" maxOccurs="unbounded"/>
+           </xs:sequence>
+           <xs:attribute ref="count"/>
+       </xs:complexType>
+    </xs:element>
+
+    <xs:element name="group_iface">
+       <xs:complexType>
+           <xs:attributeGroup ref="group_ifaceAttrGroup"/>
+       </xs:complexType>
+    </xs:element>
+
+    <xs:element name="block_items">
+       <xs:complexType>
+           <xs:group ref="block_itemsElmtGroup"/>
+           <xs:attributeGroup ref="block_itemsAttrGroup"/>
+       </xs:complexType>
+    </xs:element>
+
+    <xs:element name="bi_functional">
+       <xs:complexType>
+           <xs:group ref="bi_functionalElmtGroup"/>
+           <xs:attributeGroup ref="bi_functionalAttrGroup"/>
+       </xs:complexType>
+    </xs:element>
+
+    <xs:element name="bif_parameters">
+       <xs:complexType>
+           <xs:sequence>
+               <xs:element ref="bif_parameter" minOccurs="0" maxOccurs="unbounded" />
+           </xs:sequence>
+       </xs:complexType>
+    </xs:element>
+       
+    <xs:element name="bif_parameter">
+       <xs:complexType>
+           <xs:attributeGroup ref="bif_parameterAttrGroup"/>
+       </xs:complexType>
+    </xs:element>
+
+    <xs:element name="bif_ifaces">
+       <xs:complexType>
+           <xs:sequence>
+               <xs:element ref="bif_iface" minOccurs="0" maxOccurs="unbounded" />
+           </xs:sequence>
+           <xs:attribute ref="count"/>
+       </xs:complexType>
+    </xs:element>
+
+    <xs:element name="bif_iface">
+       <xs:complexType>
+           <xs:attributeGroup ref="bif_ifaceAttrGroup"/>
+       </xs:complexType>
+    </xs:element>
+
+    <xs:element name="bi_group">
+       <xs:complexType>
+           <xs:sequence>
+               <xs:element ref="big_ifaces"/>
+           </xs:sequence>
+           <xs:attributeGroup ref="bi_groupAttrGroup"/>
+       </xs:complexType>
+    </xs:element>
+
+    <xs:element name="big_ifaces">
+       <xs:complexType>
+           <xs:sequence>
+               <xs:element ref="big_iface" minOccurs="0" maxOccurs="unbounded" />
+           </xs:sequence>
+           <xs:attribute ref="count" />
+       </xs:complexType>
+    </xs:element>
+
+    <xs:element name="big_iface">
+       <xs:complexType>
+           <xs:attributeGroup ref="big_ifaceAttrGroup" />
+       </xs:complexType>
+    </xs:element>
+
+    <xs:element name="connections">
+       <xs:complexType>
+           <xs:sequence>
+               <xs:element ref="connection" minOccurs="0" maxOccurs="unbounded"/>
+           </xs:sequence>
+           <xs:attribute ref="count" />
+       </xs:complexType>
+    </xs:element>
+
+    <xs:element name="connection">
+       <xs:complexType>
+           <xs:attributeGroup ref="connectionAttrGroup"/>
+       </xs:complexType>
+    </xs:element>
+
+    <!-- racine du document -->
+
+    <xs:element name="blast_project">
+       <xs:complexType>
+           <xs:group ref="rootElmtGroup"/>
+       </xs:complexType>
+    </xs:element>
+
+</xs:schema>
diff --git a/save/sauv.xml b/save/sauv.xml
new file mode 100644 (file)
index 0000000..2493342
--- /dev/null
@@ -0,0 +1,24 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<blast_project>
+    <scenes count="1">
+        <scene id="0">
+            <group_item id="1" upper_group="-1" upper_item="-1" name="top group" position="-35,-35" dimension="245,195">
+                <group_ifaces count="0"/>
+            </group_item>
+            <block_items functional_count="1" group_count="0">
+                <bi_functional id="2" ref_xml="/home/ecollot/BLAST/block-1I1O.xml" ref_md5="ed0f80f406ce40c7e33ed205c8cf6002" name="block-1I1O" position="0,0" dimension="175,125">
+                    <bif_parameters>
+                        <bif_parameter name="data_width" value="8" context="user" type="string"/>
+                    </bif_parameters>
+                    <bif_ifaces count="4">
+                        <bif_iface id="0" name="clk" ref_name="clk" orientation="west" position="0"/>
+                        <bif_iface id="1" name="rst" ref_name="rst" orientation="west" position="0"/>
+                        <bif_iface id="2" name="data_i" ref_name="data_i" orientation="west" position="0.5"/>
+                        <bif_iface id="3" name="data_o" ref_name="data_o" orientation="east" position="0.5"/>
+                    </bif_ifaces>
+                </bi_functional>
+            </block_items>
+        </scene>
+    </scenes>
+    <connections/>
+</blast_project>
diff --git a/save/test.xml b/save/test.xml
new file mode 100644 (file)
index 0000000..ac40f85
--- /dev/null
@@ -0,0 +1,69 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<blast_project>
+    <scenes count="3">
+        <scene id="0" upper_scene="-1">
+            <group_item id="2" upper_item="-1" name="top group" position="-61,-306" dimension="750,483">
+                <group_ifaces count="0"/>
+            </group_item>
+            <block_items functional_count="3" group_count="1">
+                <bi_functional id="3" ref_xml="/home/ecollot/BLAST/block-1I1O.xml" ref_md5="ed0f80f406ce40c7e33ed205c8cf6002" name="block-1I1O" position="221,-271" dimension="175,125">
+                    <bif_parameters>
+                        <bif_parameter name="data_width" value="8" context="user" type="string"/>
+                    </bif_parameters>
+                    <bif_ifaces count="4">
+                        <bif_iface id="0" name="clk" ref_name="clk" orientation="west" position="0"/>
+                        <bif_iface id="1" name="rst" ref_name="rst" orientation="west" position="0"/>
+                        <bif_iface id="2" name="data_i" ref_name="data_i" orientation="west" position="0.5"/>
+                        <bif_iface id="3" name="data_o" ref_name="data_o" orientation="east" position="0.5"/>
+                    </bif_ifaces>
+                </bi_functional>
+                <bi_functional id="4" ref_xml="/home/ecollot/BLAST/block-2I2O.xml" ref_md5="96de345f776f4fabd53b74fc7625e694" name="block-2I2O" position="313,17" dimension="175,125">
+                    <bif_parameters>
+                        <bif_parameter name="data_width" value="8" context="user" type="string"/>
+                    </bif_parameters>
+                    <bif_ifaces count="6">
+                        <bif_iface id="4" name="clk" ref_name="clk" orientation="west" position="0"/>
+                        <bif_iface id="5" name="rst" ref_name="rst" orientation="west" position="0"/>
+                        <bif_iface id="6" name="data1_i" ref_name="data1_i" orientation="west" position="0.333333"/>
+                        <bif_iface id="7" name="data2_i" ref_name="data2_i" orientation="west" position="0.666667"/>
+                        <bif_iface id="8" name="data1_o" ref_name="data1_o" orientation="east" position="0.333333"/>
+                        <bif_iface id="9" name="data2_o" ref_name="data2_o" orientation="east" position="0.666667"/>
+                    </bif_ifaces>
+                </bi_functional>
+                <bi_functional id="5" ref_xml="/home/ecollot/BLAST/block-1I1O.xml" ref_md5="ed0f80f406ce40c7e33ed205c8cf6002" name="block-1I1O" position="-26,-71" dimension="175,125">
+                    <bif_parameters>
+                        <bif_parameter name="data_width" value="8" context="user" type="string"/>
+                    </bif_parameters>
+                    <bif_ifaces count="4">
+                        <bif_iface id="10" name="clk" ref_name="clk" orientation="west" position="0"/>
+                        <bif_iface id="11" name="rst" ref_name="rst" orientation="west" position="0"/>
+                        <bif_iface id="12" name="data_i" ref_name="data_i" orientation="west" position="0.5"/>
+                        <bif_iface id="13" name="data_o" ref_name="data_o" orientation="east" position="0.5"/>
+                    </bif_ifaces>
+                </bi_functional>
+                <bi_group id="6" inside_group="7" position="479,-180" dimension="175,125">
+                    <big_ifaces count="0"/>
+                </bi_group>
+            </block_items>
+        </scene>
+        <scene id="1" upper_scene="0">
+            <group_item id="7" upper_item="6" name="sub_group_2" position="-35,-35" dimension="245,195">
+                <group_ifaces count="0"/>
+            </group_item>
+            <block_items functional_count="0" group_count="1">
+                <bi_group id="8" inside_group="9" position="0,0" dimension="175,125">
+                    <big_ifaces count="0"/>
+                </bi_group>
+            </block_items>
+        </scene>
+        <scene id="2" upper_scene="1">
+            <group_item id="9" upper_item="8" name="sub_group_3" position="0,0" dimension="150,150">
+                <group_ifaces count="0"/>
+            </group_item>
+            <block_items functional_count="0" group_count="0"/>
+        </scene>
+    </scenes>
+    <connections>
+        <connection from="13" to="2"/>
+    </connections>
+</blast_project>
diff --git a/testproject.xml b/testproject.xml
new file mode 100644 (file)
index 0000000..f482cfd
--- /dev/null
@@ -0,0 +1,84 @@
+<?xml version="1.0" encoding="UTF-8" standalone="yes" ?>\r
+<blast_project>\r
+  <scenes count="2">\r
+    \r
+    <scene id="0">\r
+      \r
+      <group_item id="1" name="top" upper_group="-1" upper_item="-1" position="20,30" dimension="800,600">\r
+       <group_ifaces count="4">\r
+         <group_iface id="1" name="in_1" level="top" direction="input" orientation="west" position="0.3" />\r
+         <group_iface id="2" name="in_2" level="top" direction="input" orientation="west" position="0.6" />\r
+         <group_iface id="3" name="out_1" level="top" direction="output" orientation="south" position="0.5" />\r
+         <group_iface id="4" name="out_2" level="top" direction="output" orientation="east" position="0.5" />\r
+       </group_ifaces>\r
+      </group_item>\r
+      \r
+      <block_items functional_count="1" group_count="1">\r
+       \r
+       <bi_functional id="2" ref_xml="block-1I1O.xml" ref_md5="" name="block-1I1O_1" position="120,130" dimension="200,200">\r
+         <bif_parameters>\r
+           <bif_parameter name="data_width" value="8" />\r
+         </bif_parameters>\r
+         <bif_ifaces count="2">\r
+           <bif_iface id="5" name="in_1" ref_name="data_i" orientation="west" position="0.5" />\r
+           <bif_iface id="6" name="out_1" ref_name="data_o" orientation="east" position="0.5" />\r
+         </bif_ifaces>\r
+       </bi_functional>\r
+\r
+       <bi_group id="3" inside_group="4" position="160,150" dimension="200,200">\r
+         <big_ifaces count="4">\r
+           <big_iface id="7" ref_name="in_1" orientation="west" position="0.3" />\r
+           <big_iface id="8" ref_name="in_2" orientation="west" position="0.6" />\r
+           <big_iface id="9" ref_name="out_1" orientation="east" position="0.3" />\r
+           <big_iface id="10" ref_name="out_2" orientation="east" position="0.6" />\r
+         </big_ifaces>\r
+       </bi_group>\r
+       \r
+      </block_items>\r
+\r
+    </scene>\r
+\r
+    <scene id="1">\r
+      \r
+      <group_item id="4" upper_group="1" upper_item="3" name="subgroup_1" position="20,30" dimension="400,400">\r
+       <group_ifaces count="4">\r
+         <group_iface id="11" name="in_1" level="basic" direction="input" orientation="west" position="0.3" />\r
+         <group_iface id="12" name="in_2" level="basic" direction="input" orientation="west" position="0.6" />\r
+         <group_iface id="13" name="out_1" level="basic" direction="output" orientation="east" position="0.3" />\r
+         <group_iface id="14" name="out_2" level="basic" direction="output" orientation="east" position="0.6" />\r
+       </group_ifaces>\r
+      </group_item>\r
+      \r
+      <block_items functional_count="1" group_count="0">\r
+\r
+       <bi_functional id="5" ref_xml="block-2INO.xml" ref_md5="" name="block-2INO_1" position="120,130" dimension="200,200">\r
+         <bif_parameters>\r
+           <bif_parameter name="data_width" value="8" />\r
+         </bif_parameters>\r
+         <bif_ifaces count="4">\r
+           <bif_iface id="15" name="in_1" refname="data1_i" orientation="west" position="0.3" />\r
+           <bif_iface id="16" name="in_2" refname="data2_i" orientation="west" position="0.6" />\r
+           <bif_iface id="17" name="out_1" refname="data_o" orientation="east" position="0.3" />\r
+           <bif_iface id="18" name="out_2" refname="data_o" orientation="east" position="0.6" />\r
+         </bif_ifaces>\r
+       </bi_functional>\r
+\r
+      </block_items>\r
+\r
+    </scene>\r
+\r
+  </scenes>    \r
+\r
+  <connections>\r
+    <connection from="1" to="5" />\r
+    <connection from="2" to="8" />\r
+    <connection from="3" to="10" />\r
+    <connection from="4" to="9" />\r
+    <connection from="6" to="7" />\r
+    <connection from="11" to="15" />\r
+    <connection from="12" to="16" />\r
+    <connection from="13" to="17" />\r
+    <connection from="14" to="18" />    \r
+  </connections>\r
+\r
+</blast_project>\r