Mercurial > lcfOS
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() |