changeset 58:65acf6874a8d

Removed auto routing
author windel
date Tue, 24 Apr 2012 07:56:51 +0200
parents 143ab220aa27
children f6ea630c4057
files applications/lab/diagrameditor.py
diffstat 1 files changed, 73 insertions(+), 82 deletions(-) [+]
line wrap: on
line diff
--- a/applications/lab/diagrameditor.py	Sun Apr 22 23:10:38 2012 +0200
+++ b/applications/lab/diagrameditor.py	Tue Apr 24 07:56:51 2012 +0200
@@ -24,6 +24,7 @@
       pen = QPen(Qt.blue, 2)
       self.setPen(pen)
       self.setBrush(QBrush(pen.color()))
+      self.myshape = QPainterPath()
 
 class Connection(QGraphicsPathItem):
    """ Implementation of a connection between blocks """
@@ -39,8 +40,35 @@
       self.pen.setCapStyle(Qt.RoundCap)
       self.setPen(self.pen)
       self.arrowhead = ArrowHead(self)
+      self.vias = []
       self.setFromPort(fromPort)
       self.setToPort(toPort)
+   def mouseDoubleClickEvent(self, event):
+      pos = event.scenePos()
+      if len(self.vias) == 0:
+         tidx = 0
+      else:
+         pts = [self.pos1] + [v.pos() for v in self.vias] + [self.pos2]
+         idx = 0
+         tidx = 0
+         for p1, p2 in zip(pts[0:-1], pts[1:]):
+            l1 = QLineF(p1, p2)
+            l2 = QLineF(p1, pos)
+            l3 = QLineF(pos, p2)
+            d = l1.length() - l2.length() - l3.length()
+            print(idx, d)
+            if d > -1:
+               tidx = idx
+               print('got:',  tidx)
+            idx += 1
+      hi = HandleItem(self)
+      self.vias.insert(tidx, hi)
+      def callback(pos):
+         self.updateLineStukken()
+      hi.posChangeCallbacks.append(callback)
+      hi.setPos(pos)
+      self.updateLineStukken()
+      
    def setFromPort(self, fromPort):
       if self.fromPort:
          self.fromPort.posCallbacks.remove(self.setBeginPos)
@@ -73,11 +101,7 @@
          pass # TODO, do something useful here.
       return super(Connection, self).itemChange(change, value)
    def shape(self):
-      """ Create a shape outline using the path stroker """
-      s = super(Connection, self).shape()
-      pps = QPainterPathStroker()
-      pps.setWidth(10)
-      return pps.createStroke(s).simplified()
+      return self.myshape
    def updateLineStukken(self):
       """
          This algorithm determines the optimal routing of all signals.
@@ -86,10 +110,7 @@
       if self.pos1 is None or self.pos2 is None:
          return
 
-      # TODO: do not get the scene here?
-
-      # Determine the begin and end positions:
-      pts = editor.diagramScene.vias(self.pos1, self.pos2)
+      pts = [self.pos1] + [v.pos() for v in self.vias] + [self.pos2]
 
       self.arrowhead.setPos(self.pos2)
       if pts[-1].x() < pts[-2].x():
@@ -101,6 +122,11 @@
       for pt in pts[1:]:
          path.lineTo(pt)
       self.setPath(path)
+      """ Create a shape outline using the path stroker """
+      s = super(Connection, self).shape()
+      pps = QPainterPathStroker()
+      pps.setWidth(10)
+      self.myshape = pps.createStroke(s).simplified()
 
 class ParameterDialog(QDialog):
    def __init__(self, block, parent = None):
@@ -117,25 +143,6 @@
       self.block.setName(self.nameEdit.text())
       self.close()
 
-# TODO: merge dialogs?
-
-class AddPortDialog(QDialog):
-   def __init__(self, block, parent = None):
-      super(AddPortDialog, self).__init__(parent)
-      self.block = block
-      l = QGridLayout(self)
-      l.addWidget(QLabel('Name:', self), 0, 0)
-      self.nameEdit = QLineEdit('bla')
-      l.addWidget(self.nameEdit, 0, 1)
-      self.button = QPushButton('Ok', self)
-      l.addWidget(self.button, 1, 0)
-      self.button.clicked.connect(self.OK)
-
-   def OK(self):
-      name = self.nameEdit.text()
-      self.block.addOutput(PortItem(name, self.block, 'output'))
-      self.close()
-
 class PortItem(QGraphicsPathItem):
    """ Represents a port to a subsystem """
    def __init__(self, name, block, direction):
@@ -186,7 +193,7 @@
       return super(PortItem, self).itemChange(change, value)
    def mousePressEvent(self, event):
       if self.direction == 'output':
-         editor.diagramScene.startConnection(self)
+         self.scene().startConnection(self)
 
 class OutputPort(PortItem):
    # TODO: create a subclass OR make a member porttype
@@ -207,6 +214,8 @@
       """ Move function without moving the other selected elements """
       p = self.mapToParent(event.pos())
       self.setPos(p)
+   def mySetPos(self, p):
+      self.setPos(p)
    def itemChange(self, change, value):
       if change == self.ItemPositionChange:
          for cb in self.posChangeCallbacks:
@@ -217,6 +226,14 @@
       # Call superclass method:
       return super(HandleItem, self).itemChange(change, value)
 
+def uniqify(name, names):
+   newname = name
+   i = 1
+   while newname in names:
+      newname = name + str(i)
+      i += 1
+   return newname
+
 class BlockItem(QGraphicsRectItem):
    """ 
       Represents a block in the diagram
@@ -233,7 +250,6 @@
       self.setPen(QPen(Qt.blue, 2))
       self.setBrush(QBrush(Qt.lightGray))
       self.setFlags(self.ItemIsSelectable | self.ItemIsMovable)
-      self.setBoundingRegionGranularity(1)
       self.setCursor(QCursor(Qt.PointingHandCursor))
       self.label = QGraphicsTextItem(name, self)
       self.name = name
@@ -241,6 +257,16 @@
       self.sizer = HandleItem(self)
       self.sizer.posChangeCallbacks.append(self.changeSize) # Connect the callback
       self.sizer.setVisible(False)
+      button = QPushButton('+in')
+      button.clicked.connect(self.newInputPort)
+      self.buttonItemAddInput = QGraphicsProxyWidget(self)
+      self.buttonItemAddInput.setWidget(button)
+      self.buttonItemAddInput.setVisible(False)
+      button = QPushButton('+out')
+      button.clicked.connect(self.newOutputPort)
+      self.buttonItemAddOutput = QGraphicsProxyWidget(self)
+      self.buttonItemAddOutput.setWidget(button)
+      self.buttonItemAddOutput.setVisible(False)
 
       # Inputs and outputs of the block:
       self.inputs = []
@@ -251,9 +277,12 @@
    def editParameters(self):
       pd = ParameterDialog(self, self.window())
       pd.exec_()
-   def addPort(self):
-      pd = AddPortDialog(self, self.window())
-      pd.exec_()
+   def newInputPort(self):
+      names = [i.name for i in self.inputs + self.outputs]
+      self.addInput(PortItem(uniqify('in', names), self, 'input'))
+   def newOutputPort(self):
+      names = [i.name for i in self.inputs + self.outputs]
+      self.addOutput(PortItem(uniqify('out', names), self, 'output'))
    def setName(self, name):
       self.name = name
       self.label.setPlainText(name)
@@ -263,26 +292,24 @@
    def addOutput(self, o):
       self.outputs.append(o)
       self.updateSize()
-   def boundingRect(self):
-      rect = super(BlockItem, self).boundingRect()
-      rect.adjust(-3, -3, 3, 3)
-      return rect
 
    def contextMenuEvent(self, event):
       menu = QMenu()
       pa = menu.addAction('Parameters')
       pa.triggered.connect(self.editParameters)
-      pa = menu.addAction('Add port')
-      pa.triggered.connect(self.addPort)
       menu.exec_(event.screenPos())
    def itemChange(self, change, value):
       if change == self.ItemSelectedHasChanged:
          self.sizer.setVisible(value)
+         self.buttonItemAddInput.setVisible(value)
+         self.buttonItemAddOutput.setVisible(value)
       return super(BlockItem, self).itemChange(change, value)
 
    def updateSize(self):
       rect = self.rect()
       h, w = rect.height(), rect.width()
+      self.buttonItemAddInput.setPos(0, h + 4)
+      self.buttonItemAddOutput.setPos(w+10, h+4)
       if len(self.inputs) == 1:
          self.inputs[0].setPos(0.0, h / 2)
       elif len(self.inputs) > 1:
@@ -339,9 +366,8 @@
    def dropEvent(self, event):
       if event.mimeData().hasFormat('component/name'):
          name = bytes(event.mimeData().data('component/name')).decode()
-         b1 = BlockItem(name)
-         b1.setPos(self.mapToScene(event.pos()))
-         self.scene().addItem(b1)
+         pos = self.mapToScene(event.pos())
+         self.scene().addNewBlock(pos, name)
 
 class LibraryModel(QStandardItemModel):
    def __init__(self, parent=None):
@@ -451,6 +477,11 @@
          for port in block.inputs + block.outputs:
             if port.name == portname:
                return port
+   def addNewBlock(self, pos, name):
+      blocknames = [item.name for item in self.items() if type(item) is BlockItem]
+      b1 = BlockItem(uniqify(name, blocknames))
+      b1.setPos(pos)
+      self.addItem(b1)
    def mouseMoveEvent(self, event):
       if self.startedConnection:
          pos = event.scenePos()
@@ -472,46 +503,6 @@
       pos = port.scenePos()
       self.startedConnection.setEndPos(pos)
       self.addItem(self.startedConnection)
-   def vias(self, P1, P2):
-      """ Constructs a list of points that must be connected
-          to go from P1 to P2 """
-      def stripHits(hits):
-         """ Helper function that removes object hits """
-         hits = [hit for hit in hits if type(hit) is BlockItem]
-         return hits
-
-      def viaPoints(pA, pB):
-         # Construct intermediate points:
-         pAB1 = QPointF(pA.x(), pB.y())
-         pAB2 = QPointF(pB.x(), pA.y())
-         path1 = QPainterPath(pA)
-         path1.lineTo(pAB1)
-         path2 = QPainterPath(pA)
-         path2.lineTo(pAB2)
-         if len(stripHits(self.items(path1))) > len(stripHits(self.items(path2))):
-            pAB = pAB2
-         else:
-            pAB = pAB1
-         return [pAB]
-
-      # Determine left or right:
-      dx = QPointF(20, 0)
-      if len(stripHits(self.items(P1 + dx))) > len(stripHits(self.items(P1 - dx))):
-         p2 = P1 - dx
-      else:
-         p2 = P1 + dx
-
-      if len(stripHits(self.items(P2 + dx))) > len(stripHits(self.items(P2 - dx))):
-         p3 = P2 - dx
-      else:
-         p3 = P2 + dx
-      
-      # If pathitem:
-      pts = [P1, p2] + viaPoints(p2, p3) + [p3, P2]
-      print('line')
-      for pt in pts:
-         print(pt)
-      return pts
    def deleteItem(self, item=None):
       if item:
          if type(item) is BlockItem: