Package visgraph :: Package renderers :: Module qgraphtree
[hide private]
[frames] | no frames]

Source Code for Module visgraph.renderers.qgraphtree

  1  from PyQt4 import QtCore, QtGui, QtWebKit 
  2   
3 -class NodeColumn(QtGui.QGraphicsItem):
4
5 - def __init__(self, vg, nodes, scene, left=None, right=None):
6 QtGui.QGraphicsItem.__init__(self, scene=scene) 7 self.setZValue( -100 ) # Get behind click events... 8 9 self._v_vg = vg 10 self._v_lines = [] 11 self._v_nodes = nodes 12 13 # Remember if we srarted with something on our right or left 14 self._v_goleft = (left == None) 15 self._v_goright = (right == None) 16 17 self._v_left = left 18 self._v_right = right 19 20 offset = 0 21 for nid,nprops in nodes: 22 txt = QGraphNode(self, nid, nprops, scene=scene) 23 txt.setY( offset ) 24 offset += txt.boundingRect().height()
25
26 - def takeOverView(self):
27 self._removeLeft() 28 self._removeRight() 29 self.setX(0) 30 self.setY(0) 31 self._v_goleft = True 32 self._v_goright = True
33
34 - def _removeLeft(self):
35 left = self._v_left 36 while left: 37 nextleft = left._v_left 38 left.removeColumn() 39 left = nextleft
40
41 - def _removeRight(self):
42 right = self._v_right 43 while right: 44 nextright = right._v_right 45 right.removeColumn() 46 right = nextright
47
48 - def removeColumn(self):
49 scene = self.scene() 50 for item in self._v_lines: 51 scene.removeItem( item ) 52 scene.removeItem( self )
53
54 - def boundingRect(self):
55 return self.childrenBoundingRect()
56
57 - def paint(self, x, y, z): pass
58
59 - def getRightBoundary(self):
60 rect = self.boundingRect() 61 return self.x() + rect.width()
62
63 - def getLeftBoundary(self):
64 return self.x()
65
66 - def getYMid(self):
67 return self.y() + (self.boundingRect().height() / 2)
68
69 - def drawLinesTo(self, colnode):
70 ''' 71 Draw lines to our nodes from the specified one 72 (used when we are on the right...) 73 ''' 74 scene = self.scene() 75 colpos = colnode.scenePos() 76 colrect = colnode.boundingRect() 77 78 pen = None 79 ecolor = self._v_vg.getMeta('edgecolor') 80 if ecolor: 81 pen = QtGui.QPen( QtGui.QColor( ecolor) ) 82 83 for item in self.childItems(): 84 itpos = item.scenePos() 85 itrect = item.boundingRect() 86 87 x1 = colpos.x() + colrect.width() 88 y1 = colpos.y() + (colrect.height() / 2 ) 89 90 x2 = itpos.x() 91 y2 = itpos.y() + ( itrect.height() / 2) 92 93 lineitem = scene.addLine(x1, y1, x2, y2, pen=pen) 94 self._v_lines.append( lineitem )
95 #lineitem.setParentItem(self) 96
97 - def drawLinesFrom(self, colnode):
98 ''' 99 Draw lines from our nodes to the specified one 100 (used when we are on the left...) 101 ''' 102 scene = self.scene() 103 colpos = colnode.scenePos() 104 colrect = colnode.boundingRect() 105 106 pen = None 107 ecolor = self._v_vg.getMeta('edgecolor') 108 if ecolor: 109 pen = QtGui.QPen( QtGui.QColor( ecolor) ) 110 111 for item in self.childItems(): 112 itpos = item.scenePos() 113 itrect = item.boundingRect() 114 115 x1 = itpos.x() + itrect.width() 116 y1 = itpos.y() + ( itrect.height() / 2 ) 117 118 x2 = colpos.x() 119 y2 = colpos.y() + ( colrect.height() / 2) 120 121 lineitem = scene.addLine(x1, y1, x2, y2, pen=pen) 122 self._v_lines.append( lineitem )
123 #lineitem.setParentItem(self) 124
125 - def expandNode(self, colnode):
126 127 mymid = colnode.scenePos().y() 128 129 if self._v_goleft: 130 131 self._removeLeft() 132 133 nodes = [ (n1, self._v_vg.getNodeProps(n1)) for (eid, n1, n2, einfo) in self._v_vg.getRefsTo( colnode._v_nid ) ] 134 135 col = NodeColumn( self._v_vg, nodes, self.scene(), right=self ) 136 hiswidth = col.boundingRect().width() 137 col.setX( self.getLeftBoundary() - hiswidth - 20 ) 138 139 # Check if we want to scoot it down... 140 hismid = col.getYMid() 141 if hismid < mymid: 142 col.setY( col.y() + (mymid - hismid) ) 143 144 col.drawLinesFrom( colnode ) 145 146 self._v_left = col 147 148 if self._v_goright: 149 150 self._removeRight() 151 152 nodes = [ (n2, self._v_vg.getNodeProps(n2)) for (eid, n1, n2, einfo) in self._v_vg.getRefsFrom( colnode._v_nid ) ] 153 154 col = NodeColumn( self._v_vg, nodes, self.scene(), left=self ) 155 col.setX( self.getRightBoundary() + 20 ) 156 157 # Check if we want to scoot it down... 158 hismid = col.getYMid() 159 if hismid < mymid: 160 col.setY( col.y() + (mymid - hismid) ) 161 162 col.drawLinesTo( colnode ) 163 self._v_right = col
164
165 -class QGraphNode(QtGui.QGraphicsSimpleTextItem):
166
167 - def __init__(self, column, nid, nprops, scene=None):
168 QtGui.QGraphicsSimpleTextItem.__init__(self, nprops.get('repr', 'node:%d' % nid), scene=scene, parent=column) 169 170 self._v_nid = nid 171 self._v_nprops = nprops 172 173 color = nprops.get('color') 174 if color != None: 175 brush = QtGui.QBrush( QtGui.QColor( color ) ) 176 self.setBrush( brush )
177 178 # TODO mouseDoubleClickEvent to take over center of view. 179
180 - def mousePressEvent(self, event):
181 self.parentItem().expandNode( self ) 182 # Our scene's parent is a QGraphTreeView... 183 self.scene().parent()._sig_NodeSelected.emit(self._v_nid, self._v_nprops)
184
185 - def contextMenuEvent(self, event):
186 pos = self.scene().parent().mapFromGlobal(QtGui.QCursor.pos()) # FIXME cheating 187 self.scene().parent()._sig_NodeContextMenu.emit(pos, self._v_nid, self._v_nprops)
188
189 -class QGraphTreeView(QtGui.QGraphicsView):
190 191 _sig_NodeSelected = QtCore.pyqtSignal(int, dict) 192 _sig_NodeContextMenu = QtCore.pyqtSignal( object, int, dict ) # pos, nid, nprops 193
194 - def __init__(self, vg, nodes, parent=None):
195 QtGui.QGraphicsView.__init__(self, parent=parent) 196 scene = QtGui.QGraphicsScene(parent=self) 197 self.setScene( scene ) 198 self._v_nodecol = NodeColumn(vg, nodes, scene) 199 self._v_vg = vg
200
201 - def loadNewGraph(self, vg, nodes):
202 self._v_nodecol._removeLeft() 203 self._v_nodecol._removeRight() 204 self._v_nodecol.removeColumn() 205 206 self._v_nodecol = NodeColumn(vg, nodes, self.scene() ) 207 self._v_vg = vg
208 209 if __name__ == '__main__': 210 211 import sys 212 import visgraph.graphcore as vg_graphcore 213 214 app = QtGui.QApplication(sys.argv) 215 app.setFont( QtGui.QFont('Courier') ) 216 217 initnodes = [ (i, {'repr':'node%d' % i}) for i in xrange( 30 ) ] 218 219 # Build up a fake graph 220 vg = vg_graphcore.Graph() 221 for nid,nprops in initnodes: 222 vg.addNode(nodeid=nid, repr='node %d' % nid) 223 224 for nid,nprops in initnodes: 225 for knid,knprops in initnodes: 226 if nid == knid: 227 continue 228 vg.addEdge(nid, knid) 229 230 win = QGraphTreeView( vg, initnodes, parent=None ) 231 232 win.show() 233 app.exec_() 234