comparison python/other/diagramitems.py @ 392:bb4289c84907

Added some sort of drop event test
author Windel Bouwman
date Fri, 16 May 2014 13:05:10 +0200
parents b77f3290ac79
children
comparison
equal deleted inserted replaced
391:a139da1f44f6 392:bb4289c84907
40 40
41 41
42 class Connection(QtWidgets.QGraphicsPathItem): 42 class Connection(QtWidgets.QGraphicsPathItem):
43 """ A connection between blocks """ 43 """ A connection between blocks """
44 def __init__(self, fromPort=None, toPort=None): 44 def __init__(self, fromPort=None, toPort=None):
45 super(Connection, self).__init__() 45 super(Connection, self).__init__()
46 self.pos2 = self.fromPort = self.toPort = None 46 self.pos2 = self.fromPort = self.toPort = None
47 self.setFlags(self.ItemIsSelectable | self.ItemClipsToShape) 47 self.setFlags(self.ItemIsSelectable | self.ItemClipsToShape)
48 pen = QtGui.QPen(Qt.blue, 2, cap=Qt.RoundCap) 48 pen = QtGui.QPen(Qt.blue, 2, cap=Qt.RoundCap)
49 self.setPen(pen) 49 self.setPen(pen)
50 self.arrowhead = QtGui.QGraphicsPathItem(self) 50 self.arrowhead = QtWidgets.QGraphicsPathItem(self)
51 self.arrowhead.setPath(buildPath([QPointF(0.0, 0.0), QPointF(-6.0, 10.0), QPointF(6.0, 10.0), QPointF(0.0, 0.0)])) 51 self.arrowhead.setPath(buildPath([QtCore.QPointF(0.0, 0.0),
52 self.arrowhead.setPen(pen) 52 QtCore.QPointF(-6.0, 10.0),
53 self.arrowhead.setBrush(QtGui.QBrush(pen.color())) 53 QtCore.QPointF(6.0, 10.0),
54 self.vias = [] 54 QtCore.QPointF(0.0, 0.0)]))
55 self.setFromPort(fromPort) 55 self.arrowhead.setPen(pen)
56 self.setToPort(toPort) 56 self.arrowhead.setBrush(QtGui.QBrush(pen.color()))
57 self.vias = []
58 self.setFromPort(fromPort)
59 self.setToPort(toPort)
60
57 def getDict(self): 61 def getDict(self):
58 d = {} 62 d = {}
59 d['fromBlock'] = self.fromPort.block.name 63 d['fromBlock'] = self.fromPort.block.name
60 d['fromPort'] = self.fromPort.name 64 d['fromPort'] = self.fromPort.name
61 d['toBlock'] = self.toPort.block.name 65 d['toBlock'] = self.toPort.block.name
89 def getPos1(self): 93 def getPos1(self):
90 if self.fromPort: 94 if self.fromPort:
91 return self.fromPort.scenePos() 95 return self.fromPort.scenePos()
92 def setBeginPos(self, pos1): self.updateLineStukken() 96 def setBeginPos(self, pos1): self.updateLineStukken()
93 def setEndPos(self, endpos): 97 def setEndPos(self, endpos):
94 self.pos2 = endpos 98 self.pos2 = endpos
95 self.updateLineStukken() 99 self.updateLineStukken()
96 def itemChange(self, change, value): 100 def itemChange(self, change, value):
97 if change == self.ItemSelectedHasChanged: 101 if change == self.ItemSelectedHasChanged:
98 for via in self.vias: 102 for via in self.vias:
99 via.setVisible(value) 103 via.setVisible(value)
100 return super(Connection, self).itemChange(change, value) 104 return super(Connection, self).itemChange(change, value)
101 def shape(self): return self.myshape 105
106 def shape(self):
107 return self.myshape
108
102 def updateLineStukken(self): 109 def updateLineStukken(self):
103 """ 110 """
104 This algorithm determines the optimal routing of all signals. 111 This algorithm determines the optimal routing of all signals.
105 TODO: implement nice automatic line router 112 TODO: implement nice automatic line router
106 """ 113 """
107 pos1 = self.getPos1() 114 pos1 = self.getPos1()
108 pos2 = self.pos2 115 pos2 = self.pos2
109 if pos1 is None or pos2 is None: 116 if pos1 is None or pos2 is None:
110 return 117 return
111 scene = self.scene() 118 scene = self.scene()
112 vias = [pos1 + QPointF(20, 0)] + self.vias + [pos2 + QPointF(-20, 0)] 119 vias = [pos1 + QtCore.QPointF(20, 0)] + self.vias + [pos2 + QtCore.QPointF(-20, 0)]
113 if scene: 120 if scene:
114 litem = QtGui.QGraphicsLineItem() 121 litem = QtWidgets.QGraphicsLineItem()
115 litem.setFlags(self.ItemIsSelectable) 122 litem.setFlags(self.ItemIsSelectable)
116 scene.addItem(litem) 123 scene.addItem(litem)
117 for p1, p2 in zip(vias[:-1], vias[1:]): 124 for p1, p2 in zip(vias[:-1], vias[1:]):
118 line = QLineF(p1, p2) 125 line = QtCore.QLineF(p1, p2)
119 litem.setLine(line) 126 litem.setLine(line)
120 citems = scene.collidingItems(litem) 127 citems = scene.collidingItems(litem)
121 citems = [i for i in citems if type(i) is Block] 128 citems = [i for i in citems if type(i) is Block]
122 scene.removeItem(litem) 129 scene.removeItem(litem)
123 pts = [pos1] + vias + [pos2] 130 pts = [pos1] + vias + [pos2]
133 140
134 class PortItem(QtWidgets.QGraphicsPathItem): 141 class PortItem(QtWidgets.QGraphicsPathItem):
135 """ Represents a port to a subsystem """ 142 """ Represents a port to a subsystem """
136 def __init__(self, name, block): 143 def __init__(self, name, block):
137 super(PortItem, self).__init__(block) 144 super(PortItem, self).__init__(block)
138 self.textItem = QtGui.QGraphicsTextItem(self) 145 self.textItem = QtWidgets.QGraphicsTextItem(self)
139 self.connection = None 146 self.connection = None
140 self.block = block 147 self.block = block
141 self.setCursor(QtGui.QCursor(Qt.CrossCursor)) 148 self.setCursor(QtGui.QCursor(Qt.CrossCursor))
142 self.setPen(QtGui.QPen(Qt.blue, 2, cap=Qt.RoundCap)) 149 self.setPen(QtGui.QPen(Qt.blue, 2, cap=Qt.RoundCap))
143 self.name = name 150 self.name = name
158 if change == self.ItemScenePositionHasChanged: 165 if change == self.ItemScenePositionHasChanged:
159 for cb in self.posCallbacks: cb(value) 166 for cb in self.posCallbacks: cb(value)
160 return value 167 return value
161 return super(PortItem, self).itemChange(change, value) 168 return super(PortItem, self).itemChange(change, value)
162 169
170
163 class OutputPort(PortItem): 171 class OutputPort(PortItem):
164 def __init__(self, name, block, d=10.0): 172 def __init__(self, name, block, d=10.0):
165 super(OutputPort, self).__init__(name, block) 173 super().__init__(name, block)
166 self.setPath(buildPath([QPointF(0.0, -d), QPointF(d, 0), QPointF(0.0, d)])) 174 self.setPath(buildPath([QtCore.QPointF(0.0, -d), QtCore.QPointF(d, 0),
167 def mousePressEvent(self, event): 175 QtCore.QPointF(0.0, d)]))
168 self.scene().startConnection(self) 176
177 def mousePressEvent(self, event):
178 self.scene().startConnection(self)
179
169 180
170 class InputPort(PortItem): 181 class InputPort(PortItem):
171 def __init__(self, name, block, d=10.0): 182 def __init__(self, name, block, d=10.0):
172 super(InputPort, self).__init__(name, block) 183 super().__init__(name, block)
173 self.setPath(buildPath([QPointF(-d, -d), QPointF(0, 0), QPointF(-d, d)])) 184 self.setPath(buildPath([QtCore.QPointF(-d, -d), QtCore.QPointF(0, 0),
185 QtCore.QPointF(-d, d)]))
174 186
175 class Handle(QtWidgets.QGraphicsEllipseItem): 187 class Handle(QtWidgets.QGraphicsEllipseItem):
176 """ A handle that can be moved by the mouse """ 188 """ A handle that can be moved by the mouse """
177 def __init__(self, dx=10.0, parent=None): 189 def __init__(self, dx=10.0, parent=None):
178 super(Handle, self).__init__(QtCore.QRectF(-0.5*dx,-0.5*dx,dx,dx), parent) 190 super(Handle, self).__init__(QtCore.QRectF(-0.5*dx,-0.5*dx,dx,dx), parent)
184 def mouseMoveEvent(self, event): 196 def mouseMoveEvent(self, event):
185 """ Move function without moving the other selected elements """ 197 """ Move function without moving the other selected elements """
186 p = self.mapToParent(event.pos()) 198 p = self.mapToParent(event.pos())
187 self.setPos(p) 199 self.setPos(p)
188 200
201
189 class ResizeSelectionHandle(Handle): 202 class ResizeSelectionHandle(Handle):
190 def __init__(self, position, block): 203 def __init__(self, position, block):
191 super(ResizeSelectionHandle, self).__init__(dx=12, parent=block) 204 super(ResizeSelectionHandle, self).__init__(dx=12, parent=block)
192 self.position = position 205 self.position = position
193 self.block = block 206 self.block = block
194 if position in [Position.TOP_LEFT, Position.BOTTOM_RIGHT]: 207 if position in [Position.TOP_LEFT, Position.BOTTOM_RIGHT]:
195 self.setCursor(QtGui.QCursor(Qt.SizeFDiagCursor)) 208 self.setCursor(QtGui.QCursor(Qt.SizeFDiagCursor))
196 elif position in [Position.TOP_RIGHT, Position.BOTTOM_LEFT]: 209 elif position in [Position.TOP_RIGHT, Position.BOTTOM_LEFT]:
197 self.setCursor(QCursor(Qt.SizeBDiagCursor)) 210 self.setCursor(QtGui.QCursor(Qt.SizeBDiagCursor))
198 elif position in [Position.TOP, Position.BOTTOM]: 211 elif position in [Position.TOP, Position.BOTTOM]:
199 self.setCursor(QCursor(Qt.SizeVerCursor)) 212 self.setCursor(QtGui.QCursor(Qt.SizeVerCursor))
200 elif position in [Position.LEFT, Position.RIGHT]: 213 elif position in [Position.LEFT, Position.RIGHT]:
201 self.setCursor(QtGui.QCursor(Qt.SizeHorCursor)) 214 self.setCursor(QtGui.QCursor(Qt.SizeHorCursor))
202 def mouseMoveEvent(self, event): 215
203 self.block.sizerMoveEvent(self, event.scenePos()) 216 def mouseMoveEvent(self, event):
217 self.block.sizerMoveEvent(self, event.scenePos())
218
204 219
205 class Block(QtWidgets.QGraphicsRectItem): 220 class Block(QtWidgets.QGraphicsRectItem):
206 """ Represents a block in the diagram. """ 221 """ Represents a block in the diagram. """
207 def __init__(self, name='Untitled', parent=None): 222 def __init__(self, name='Untitled', parent=None):
208 super(Block, self).__init__(parent) 223 super(Block, self).__init__(parent)
228 self.buttonItemAddOutput.setVisible(False) 243 self.buttonItemAddOutput.setVisible(False)
229 # Inputs and outputs of the block: 244 # Inputs and outputs of the block:
230 self.inputs = [] 245 self.inputs = []
231 self.outputs = [] 246 self.outputs = []
232 self.changeSize(2,2) 247 self.changeSize(2,2)
248
233 def editParameters(self): 249 def editParameters(self):
234 pd = ParameterDialog(self, self.window()) 250 pd = ParameterDialog(self, self.window())
235 pd.exec_() 251 pd.exec_()
252
236 def newInputPort(self): 253 def newInputPort(self):
237 names = [i.name for i in self.inputs + self.outputs] 254 names = [i.name for i in self.inputs + self.outputs]
238 self.addInput(InputPort(uniqify('in', names), self)) 255 self.addInput(InputPort(uniqify('in', names), self))
256
239 def newOutputPort(self): 257 def newOutputPort(self):
240 names = [i.name for i in self.inputs + self.outputs] 258 names = [i.name for i in self.inputs + self.outputs]
241 self.addOutput(OutputPort(uniqify('out', names), self)) 259 self.addOutput(OutputPort(uniqify('out', names), self))
260
242 def setName(self, name): self.label.setPlainText(name) 261 def setName(self, name): self.label.setPlainText(name)
262
243 def getName(self): return self.label.toPlainText() 263 def getName(self): return self.label.toPlainText()
264
244 name = property(getName, setName) 265 name = property(getName, setName)
245 def getDict(self): 266 def getDict(self):
246 d = {'x': self.scenePos().x(), 'y': self.scenePos().y()} 267 d = {'x': self.scenePos().x(), 'y': self.scenePos().y()}
247 rect = self.rect() 268 rect = self.rect()
248 d.update({'width': rect.width(), 'height': rect.height()}) 269 d.update({'width': rect.width(), 'height': rect.height()})
257 for inp in d['inputs']: 278 for inp in d['inputs']:
258 self.addInput(InputPort(inp['name'], self)) 279 self.addInput(InputPort(inp['name'], self))
259 for outp in d['outputs']: 280 for outp in d['outputs']:
260 self.addOutput(OutputPort(outp['name'], self)) 281 self.addOutput(OutputPort(outp['name'], self))
261 Dict = property(getDict, setDict) 282 Dict = property(getDict, setDict)
283
262 def addInput(self, i): 284 def addInput(self, i):
263 self.inputs.append(i) 285 self.inputs.append(i)
264 self.updateSize() 286 self.updateSize()
287
265 def addOutput(self, o): 288 def addOutput(self, o):
266 self.outputs.append(o) 289 self.outputs.append(o)
267 self.updateSize() 290 self.updateSize()
291
268 def contextMenuEvent(self, event): 292 def contextMenuEvent(self, event):
269 menu = QMenu() 293 menu = QtWidgets.QMenu()
270 pa = menu.addAction('Parameters') 294 pa = menu.addAction('Parameters')
271 pa.triggered.connect(self.editParameters) 295 pa.triggered.connect(self.editParameters)
272 menu.exec_(event.screenPos()) 296 menu.exec_(event.screenPos())
273 def itemChange(self, change, value): 297 def itemChange(self, change, value):
274 if change == self.ItemSelectedHasChanged: 298 if change == self.ItemSelectedHasChanged:
279 else: 303 else:
280 [h.setVisible(False) for h in self.selectionHandles] 304 [h.setVisible(False) for h in self.selectionHandles]
281 305
282 return super(Block, self).itemChange(change, value) 306 return super(Block, self).itemChange(change, value)
283 def hoverEnterEvent(self, event): 307 def hoverEnterEvent(self, event):
284 if not self.isSelected(): 308 if not self.isSelected():
285 self.repositionAndShowHandles() 309 self.repositionAndShowHandles()
286 super(Block, self).hoverEnterEvent(event) 310 super().hoverEnterEvent(event)
287 def hoverLeaveEvent(self, event): 311 def hoverLeaveEvent(self, event):
288 if not self.isSelected(): 312 if not self.isSelected():
289 [h.setVisible(False) for h in self.selectionHandles] 313 [h.setVisible(False) for h in self.selectionHandles]
290 super(Block, self).hoverLeaveEvent(event) 314 super().hoverLeaveEvent(event)
291 def myDelete(self): 315 def myDelete(self):
292 for p in self.inputs + self.outputs: 316 for p in self.inputs + self.outputs:
293 if p.connection: p.connection.myDelete() 317 if p.connection: p.connection.myDelete()
294 self.scene().removeItem(self) 318 self.scene().removeItem(self)
295 def repositionAndShowHandles(self): 319 def repositionAndShowHandles(self):
326 for inp, y in zip(self.inputs, equalSpace(len(self.inputs), h)): 350 for inp, y in zip(self.inputs, equalSpace(len(self.inputs), h)):
327 inp.setPos(0.0, y) 351 inp.setPos(0.0, y)
328 for outp, y in zip(self.outputs, equalSpace(len(self.outputs), h)): 352 for outp, y in zip(self.outputs, equalSpace(len(self.outputs), h)):
329 outp.setPos(w, y) 353 outp.setPos(w, y)
330 def setCenterAndSize(self, center, size): 354 def setCenterAndSize(self, center, size):
331 self.changeSize(size.width(), size.height()) 355 self.changeSize(size.width(), size.height())
332 p = QPointF(size.width(), size.height()) 356 p = QtCore.QPointF(size.width(), size.height())
333 self.setPos(center - p / 2) 357 self.setPos(center - p / 2)
334 def changeSize(self, w, h): 358 def changeSize(self, w, h):
335 minw = 150 359 minw = 150
336 minh = 50 360 minh = 50
337 h = minh if h < minh else h 361 h = minh if h < minh else h
338 w = minw if w < minw else w 362 w = minw if w < minw else w
339 self.setRect(0.0, 0.0, w, h) 363 self.setRect(0.0, 0.0, w, h)
340 rect = self.label.boundingRect() 364 rect = self.label.boundingRect()
341 self.label.setPos((w - rect.width()) / 2, (h - rect.height()) / 2) 365 self.label.setPos((w - rect.width()) / 2, (h - rect.height()) / 2)
342 self.updateSize() 366 self.updateSize()
343 367
344 368
345 class CodeBlock(Block): 369 class CodeBlock(Block):
346 def __init__(self, name='Untitled', parent=None): 370 def __init__(self, name='Untitled', parent=None):
347 super(CodeBlock, self).__init__(name, parent) 371 super(CodeBlock, self).__init__(name, parent)
365 return c 389 return c
366 390
367 391
368 class DiagramBlock(Block): 392 class DiagramBlock(Block):
369 def __init__(self, name='Untitled', parent=None): 393 def __init__(self, name='Untitled', parent=None):
370 super(DiagramBlock, self).__init__(name, parent) 394 super(DiagramBlock, self).__init__(name, parent)
371 self.subModel = DiagramScene() 395 self.subModel = DiagramScene()
372 self.subModel.containingBlock = self 396 self.subModel.containingBlock = self
373 397
374 def setDict(self, d): 398 def setDict(self, d):
375 self.subModel.Dict = d['submodel'] 399 self.subModel.Dict = d['submodel']
376 400
377 def mouseDoubleClickEvent(self, event): 401 def mouseDoubleClickEvent(self, event):
378 # descent into child diagram 402 # descent into child diagram
379 #self.editParameters() 403 #self.editParameters()
380 print('descent') 404 print('descent')
381 scene = self.scene() 405 scene = self.scene()
382 if scene: 406 if scene:
383 for view in scene.views(): 407 for view in scene.views():
384 view.diagram = self.subModel 408 view.diagram = self.subModel
385 view.zoomAll() 409 view.zoomAll()
386 410
387 411
388 class DiagramScene(QtWidgets.QGraphicsScene): 412 class DiagramScene(QtWidgets.QGraphicsScene):
389 """ A diagram scene consisting of blocks and connections """ 413 """ A diagram scene consisting of blocks and connections """
390 structureChanged = pyqtSignal() 414 structureChanged = pyqtSignal()