# HG changeset patch # User windel # Date 1335247011 -7200 # Node ID 65acf6874a8d63e67058416eaa7933fed34b43e7 # Parent 143ab220aa270e4301caeb82f268d0e1c6fbb36c Removed auto routing diff -r 143ab220aa27 -r 65acf6874a8d applications/lab/diagrameditor.py --- 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: