Advertisement
Guest User

QGraphicsView deletion problem

a guest
Jan 1st, 2013
116
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Python 10.81 KB | None | 0 0
  1. import sys
  2. import weakref
  3. import math
  4. from PySide import QtCore, QtGui
  5.  
  6.  
  7.  
  8. ###
  9. class Edge(QtGui.QGraphicsItem):
  10.     Type = QtGui.QGraphicsItem.UserType + 2
  11.  
  12.     def __init__(self, sourceNode, destNode):
  13.         QtGui.QGraphicsItem.__init__(self)
  14.         #
  15.         self.sourcePoint = QtCore.QPointF()
  16.         self.destPoint = QtCore.QPointF()
  17.         self.setAcceptedMouseButtons(QtCore.Qt.NoButton)
  18.         self.source = weakref.ref(sourceNode)
  19.         self.dest = weakref.ref(destNode)
  20.         self.source().addEdge(self)
  21.         self.dest().addEdge(self)
  22.         self.adjust()
  23.  
  24.     def type(self):
  25.         return Edge.Type
  26.  
  27.     def sourceNode(self):
  28.         return self.source()
  29.  
  30.     def destNode(self):
  31.         return self.dest()
  32.  
  33.     def adjust(self):
  34.         # do we have a line to draw ?
  35.         if  self.source() and self.dest():
  36.             line = QtCore.QLineF(self.mapFromItem(self.source(), 0, 0), self.mapFromItem(self.dest(), 0, 0))
  37.             length = line.length()
  38.             if length > 20:
  39.                 edgeOffset = QtCore.QPointF((line.dx() * 10) / length, (line.dy() * 10) / length)
  40.                 self.prepareGeometryChange()
  41.                 self.sourcePoint = line.p1() + edgeOffset
  42.                 self.destPoint   = line.p2() - edgeOffset
  43.             else: # want to make sure line not drawn over node blob
  44.                 self.prepareGeometryChange()
  45.                 self.sourcePoint = self.destPoint
  46.  
  47.     def boundingRect(self):
  48.         # do we have a line to draw ?
  49.         if not self.source() or not self.dest():
  50.             return QtCore.QRectF()
  51.         else:
  52.             extra = 1
  53.             return QtCore.QRectF(self.sourcePoint,
  54.                                  QtCore.QSizeF(self.destPoint.x() - self.sourcePoint.x(),
  55.                                                self.destPoint.y() - self.sourcePoint.y())).normalized().adjusted(-extra, -extra, extra, extra)
  56.  
  57.     def paint(self, painter, option, widget):
  58.         if self.source() and self.dest():
  59.             # Draw the line itself.
  60.             line = QtCore.QLineF(self.sourcePoint, self.destPoint)
  61.             if line.length() > 0.0:
  62.                 painter.setPen(QtGui.QPen(QtCore.Qt.black, 1, QtCore.Qt.SolidLine, QtCore.Qt.RoundCap, QtCore.Qt.RoundJoin))
  63.                 painter.drawLine(line)
  64.  
  65. ###
  66. class Node(QtGui.QGraphicsItem):
  67.     Type = QtGui.QGraphicsItem.UserType + 1
  68.  
  69.     def __init__(self, graphWidget, time, temp, pos):
  70.         QtGui.QGraphicsItem.__init__(self)
  71.  
  72.         self.graph = weakref.ref(graphWidget)
  73.         self.edgeList = []
  74.         self.set_index(pos)
  75.         self.setFlag(QtGui.QGraphicsItem.ItemIsMovable)
  76.         self.setFlag(QtGui.QGraphicsItem.ItemSendsGeometryChanges)
  77.         self.setCacheMode(self.DeviceCoordinateCache)
  78.         self.setZValue(-1)
  79.         #
  80.         self.temp = temp
  81.         self.time = time
  82.         x,y = self.map_temptime_to_pos()
  83.         self.setPos(x,y)
  84.         self.marker = False
  85.  
  86.  
  87.     def type(self):
  88.         return Node.Type
  89.  
  90.     def edges(self):
  91.         return self.edgeList
  92.  
  93.     def addEdge(self, edge):
  94.         self.edgeList.append(weakref.ref(edge))
  95.  
  96.     def set_index(self, index):
  97.         self.index = index
  98.  
  99.     def get_prev_edge(self):
  100.         index = 1000
  101.         edge = False
  102.         for e in self.edgeList:
  103.             sn = e().source().index
  104.             dn = e().dest().index
  105.             if sn < index:
  106.                 index = sn
  107.                 edge = e
  108.             if dn < index:
  109.                 index = dn
  110.                 edge = e
  111.         return edge
  112.  
  113.     def get_next_edge(self):
  114.         index = -1
  115.         edge = False
  116.         for e in self.edgeList:
  117.             sn = e().source().index
  118.             dn = e().dest().index
  119.             if sn > index:
  120.                 index = sn
  121.                 edge = e
  122.             if dn > index:
  123.                 index = dn
  124.                 edge = e
  125.         return edge
  126.  
  127.     def map_pos_to_temptime(self, value=False):
  128.         """ given screen pos return temp,time
  129.            - optional value indicates actual pos from event
  130.            failed attempt to correct for 0,0 position after deletion """
  131.         if value:
  132.             x = value.x()
  133.             y = value.y()
  134.         else:
  135.             x = self.x()
  136.             y = self.y()
  137.         print "node at",x,y
  138.         height = self.graph().size[3]
  139.         time = x / self.graph().graph_width_ratio
  140.         temp = (height - y ) / self.graph().graph_height_ratio
  141.         return (time, temp)
  142.  
  143.     def map_temptime_to_pos(self):
  144.         x = self.time * self.graph().graph_width_ratio
  145.         y = self.graph().size[3] - self.temp * self.graph().graph_height_ratio
  146.         return (x,y)
  147.  
  148.     def boundingRect(self):
  149.         adjust = 2.0
  150.         return QtCore.QRectF(-10 - adjust, -10 - adjust,
  151.                              22 + adjust, 23 + adjust)
  152.  
  153.     def paint(self, painter, option, widget):
  154.         painter.drawLine(QtCore.QLineF(6,-40,6,-2))
  155.         painter.setPen(QtCore.Qt.NoPen)
  156.         painter.setBrush(QtCore.Qt.lightGray)
  157.         painter.drawEllipse(-10, -10, 20, 20)
  158.         gradient = QtGui.QRadialGradient(0, 0, 22)
  159.         if option.state & QtGui.QStyle.State_Sunken: # selected
  160.             gradient.setColorAt(0, QtGui.QColor(QtCore.Qt.darkGreen).lighter(120))
  161.         else:
  162.             gradient.setColorAt(1, QtCore.Qt.blue)
  163.         painter.setBrush(QtGui.QBrush(gradient))
  164.         painter.setPen(QtGui.QPen(QtCore.Qt.black, 0))
  165.         painter.drawEllipse(-6, -6, 12, 12)
  166.  
  167.  
  168.     def itemChange(self, change, value):
  169.         if change == QtGui.QGraphicsItem.ItemPositionChange:
  170.             print "redraw my edges", value
  171.             print "current:",self.temp, self.time
  172.             for edge in self.edgeList:
  173.                 edge().adjust()
  174.         #return super(Node, self).itemChange(change, value)
  175.         return value
  176.  
  177.     def mousePressEvent(self, event):
  178.         if not self.graph().inhibit_edit:
  179.             self.update()
  180.             print "\nNode pressed"
  181.             QtGui.QGraphicsItem.mousePressEvent(self, event)
  182.  
  183.     def mouseReleaseEvent(self, event):
  184.         if not self.graph().inhibit_edit:
  185.             timetemp = self.map_pos_to_temptime()
  186.             self.time = timetemp[0]
  187.             self.temp = timetemp[1]
  188.             #self.update()
  189.             print "Node released\n"
  190.             #
  191.             nodes = self.graph().get_ordered_nodes()
  192.             # Check for delete
  193.             i = self.index
  194.             prevtime = -1000
  195.             nexttime = 1000
  196.             if i > 1:
  197.                 prevtime = nodes[i-2].time
  198.             if i < len(nodes):
  199.                 nexttime = nodes[i].time
  200.             print prevtime, self.time, nexttime
  201.             if not (prevtime < self.time < nexttime):
  202.                 print "deleting"
  203.                 self.graph().delete_node(i)
  204.             #
  205.             self.update() #! not required
  206.             QtGui.QGraphicsItem.mouseReleaseEvent(self, event)
  207.  
  208.  
  209.  
  210. ###
  211. class GraphWidget(QtGui.QGraphicsView):
  212.     def __init__(self):
  213.         QtGui.QGraphicsView.__init__(self)
  214.         self.size = (-30, 30, 600, 400)
  215.         #
  216.         scene = QtGui.QGraphicsScene(self)
  217.         scene.setItemIndexMethod(QtGui.QGraphicsScene.NoIndex)
  218.         scene.setSceneRect(self.size[0],self.size[1],self.size[2],self.size[3])
  219.         self.setScene(scene)
  220.         self.setCacheMode(QtGui.QGraphicsView.CacheBackground)
  221.         self.setRenderHint(QtGui.QPainter.Antialiasing)
  222.         self.setTransformationAnchor(QtGui.QGraphicsView.AnchorUnderMouse)
  223.         self.setResizeAnchor(QtGui.QGraphicsView.AnchorViewCenter)
  224.         #
  225.         self.maxtemp = 300
  226.         self.maxtime = 160
  227.         self.nodecount = 0
  228.         self.calc_upper_limits()
  229.         #
  230.         self.scale(0.8, 0.8)
  231.         self.setMinimumSize(600, 400)
  232.         self.setWindowTitle(self.tr("Elastic Nodes"))
  233.         self.inhibit_edit = False
  234.  
  235.     def calc_upper_limits(self):
  236.         self.toptemp = (self.maxtemp / 100 + 1) * 100
  237.         self.toptime = (int(self.maxtime) / 30 + 1) * 30
  238.         self.graph_width_ratio = float(self.size[2]) /self.toptime
  239.         self.graph_height_ratio = float(self.size[3]) / self.toptemp
  240.  
  241.     def add_node(self, time, temp, marker=False, pos=-1):
  242.         self.nodecount += 1
  243.         scene = self.scene()
  244.         # Insert Node into scene
  245.         node = Node(self, time, temp, self.nodecount)
  246.         scene.addItem(node)
  247.         # Insert new edges
  248.         nodes = self.get_ordered_nodes()
  249.         if len(nodes) > 1:
  250.             e = Edge(nodes[-2], node)
  251.             scene.addItem(e)
  252.  
  253.  
  254.     def delete_node(self, index):
  255.         """ delete node at index
  256.            - reindex nodes, edges
  257.        """
  258.         nodes = self.get_ordered_nodes()
  259.         node = nodes[index-1]
  260.         # find preceding and next nodes
  261.         pn = False
  262.         nn = False
  263.         if index > 1:
  264.             pn = nodes[index-2]
  265.         if index < len(nodes):
  266.             nn = nodes[index]
  267.         # disconnect edges between pn->node and node->nn
  268.         if pn:
  269.             e_index = pn.edges().index(pn.get_next_edge())
  270.             print " removing edge",e_index,'from pn', pn.edges()
  271.             pn.edges().pop(e_index)
  272.         if nn:
  273.             e_index = nn.edges().index(nn.get_prev_edge())
  274.             print " removing edge",e_index,'from nn', nn.edges()
  275.             nn.edges().pop(e_index)
  276.         # add new edge between pn,nn -if node not an end
  277.         if pn and nn:
  278.             self.scene().addItem(Edge(pn, nn))
  279.         # force first node to time=0
  280.         if not pn:
  281.             nn.force_to_Tzero()
  282.         # remove edges belonging to node
  283.         for e in node.edges():
  284.             e().hide()
  285.             self.scene().removeItem(e())
  286.             del(e)
  287.         node.hide()
  288.         # remove node from scene
  289.         self.scene().removeItem(node)
  290.         del(node)
  291.         # start from fresh nodes list
  292.         # correct node numbering for this and following nodes and edges
  293.         nodes = self.get_ordered_nodes()
  294.         for i in range(len(nodes)):
  295.             n = nodes[i]
  296.             print "reindexing", n.index,i+1
  297.             #n.prepareGeometryChange()
  298.             n.set_index(i+1)
  299.         self.nodecount -= 1
  300.  
  301.  
  302.     def get_ordered_nodes(self):
  303.         nodes = [item for item in self.scene().items() if isinstance(item, Node)]
  304.         nodes.sort(key=lambda n: n.index)
  305.         return nodes
  306.  
  307.  
  308.     def mousePressEvent(self, event):
  309.         print "GraphWidget mouse"
  310.         QtGui.QGraphicsView.mousePressEvent(self, event)
  311.  
  312.  
  313.     def drawBackground(self, painter, rect):
  314.         sceneRect = self.sceneRect()
  315.  
  316.  
  317. if __name__ == "__main__":
  318.     app = QtGui.QApplication(sys.argv)
  319.     widget = GraphWidget()
  320.     widget.add_node(0,    25)
  321.     widget.add_node(30,  40)
  322.     widget.add_node(80,  60)
  323.     widget.add_node(100,  80)
  324.     widget.show()
  325.     sys.exit(app.exec_())
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement