00001 from PyQt4.QtGui import *
00002 from PyQt4.QtCore import *
00003
00004 class NodeBoxGraphicsView(QGraphicsWidget):
00005 zoomLevels = [0.1, 0.25, 0.5, 0.75]
00006 zoom = 1.0
00007 zoom = .5
00008 while zoom <= 20.0:
00009 zoomLevels.append(zoom)
00010 zoom += 1.0
00011
00012 def __init__(self, parent=None):
00013 QGraphicsWidget.__init__(self, parent)
00014 self.setFlag(QGraphicsItem.ItemClipsToShape, True)
00015 self.setFocusPolicy(Qt.ClickFocus)
00016 self._rect = QRectF(0, 0, 1000, 1000)
00017 self._shape = QPainterPath()
00018 self._shape.addRect(self._rect)
00019 self._canvas = None
00020 self._dirty = True
00021 self.mousedown = False
00022 self.rightdown = False
00023 self.mousePosition = QPointF(0, 0)
00024 self.mouseDCPosition = QPointF(0, 0)
00025 self.mousedoubleclick = False
00026 self.keydown = False
00027 self.key = None
00028 self.keycode = None
00029 self.scrollwheel = False
00030 self.wheeldelta = 0.0
00031 self._zoom = 1.0
00032
00033
00034
00035 def boundingRect(self):
00036 return self._rect
00037
00038 def shape(self):
00039 return self._shape
00040
00041 def _check_cache(self):
00042 cacheMode = self.cacheMode()
00043 DeviceCoordinateCache = QGraphicsItem.DeviceCoordinateCache
00044 NoCache = QGraphicsItem.NoCache
00045 if self.canvas is not None:
00046 if self.document.animationTimer is not None:
00047 cache = False
00048 elif len(self.canvas) > 400:
00049 x, y, width, height = self._rect.getRect()
00050 cache = True
00051 if width > 1000 or height > 1000 or \
00052 not (width * self.zoom <= 1200 and height * self.zoom <= 1200):
00053 cache = False
00054 else:
00055 cache = False
00056 if cache and cacheMode != DeviceCoordinateCache:
00057 self.setCacheMode(DeviceCoordinateCache)
00058 elif not cache and cacheMode != NoCache:
00059 self.setCacheMode(NoCache)
00060 elif cacheMode != NoCache:
00061 self.setCacheMode(QNoCache)
00062
00063 def _get_canvas(self):
00064 return self._canvas
00065
00066 def _set_canvas(self, canvas):
00067 self._canvas = canvas
00068 if canvas is not None:
00069 x, y, width, height = self._rect.getRect()
00070 size = int(width), int(height)
00071 if size != self.canvas.size:
00072 width, height = self.canvas.size
00073 scene = self._scene
00074 self._rect = rect = QRectF(0, 0, width, height)
00075 scene.setSceneRect(rect)
00076 self._shape = shape = QPainterPath()
00077 shape.addRect(rect)
00078 self._check_cache()
00079 self.markDirty()
00080 canvas = property(_get_canvas, _set_canvas)
00081
00082 def _get_zoom(self):
00083 return self._zoom
00084
00085 def _set_zoom(self, zoom):
00086 self._zoom = zoom
00087 self.document.zoomLevel.setText("%i%%" % (self._zoom * 100.0))
00088 self.document.zoomSlider.setValue(self._zoom * 100.0)
00089 self._check_cache()
00090 transform = QTransform()
00091 transform.scale(self.zoom, self.zoom)
00092 self.superView.setTransform(transform)
00093 zoom = property(_get_zoom, _set_zoom)
00094
00095 def findNearestZoomIndex(self, zoom):
00096 """Returns the nearest zoom level, and whether we found a direct, exact
00097 match or a fuzzy match."""
00098 try:
00099 idx = self.zoomLevels.index(zoom)
00100 return idx, True
00101 except ValueError:
00102 idx = 0
00103 try:
00104 while self.zoomLevels[idx] < zoom:
00105 idx += 1
00106 except KeyError:
00107 idx = len(self.zoomLevels) - 1
00108 return idx, False
00109
00110 def zoomIn_(self):
00111 idx, direct = self.findNearestZoomIndex(self.zoom)
00112
00113
00114
00115 if direct:
00116 idx += 1
00117 idx = max(min(idx, len(self.zoomLevels)-1), 0)
00118 self.zoom = self.zoomLevels[idx]
00119
00120 def zoomOut_(self):
00121 idx, direct = self.findNearestZoomIndex(self.zoom)
00122 idx -= 1
00123 idx = max(min(idx, len(self.zoomLevels)-1), 0)
00124 self.zoom = self.zoomLevels[idx]
00125
00126 def zoomTo_(self, value):
00127 self.zoom = value
00128
00129 def zoomToFit_(self):
00130 w, h = self.canvas.size
00131 factor = min(self._viewPort.width() / float(w), self._viewPort.height() / float(h))
00132 self.zoom = factor
00133
00134 def dragZoom_(self, value):
00135 self.zoom = value / 100.0
00136
00137 def markDirty(self, redraw=True):
00138 self._dirty = True
00139 if redraw:
00140 self._viewPort.update()
00141
00142 def _updateImage(self, painter):
00143 if self.canvas is None: return
00144 painter._screen = True
00145 try:
00146 painter.save()
00147 self.canvas.draw(painter)
00148 except:
00149
00150 etype, value, tb = sys.exc_info()
00151 if tb.tb_next is not None:
00152 tb = tb.tb_next
00153 traceback.print_exception(etype, value, tb)
00154 data = "".join(traceback.format_exception(etype, value, tb))
00155 outputView = self.document.outputView
00156 outputView.setTextColor(QColor(255, 0, 0))
00157 outputView.insertPlainText(data)
00158 finally:
00159 painter.restore()
00160
00161 def paint(self, painter, item, widget):
00162 if self._dirty:
00163 self._updateImage(painter)
00164
00165 def mousePressEvent(self, event):
00166 self.mousePosition = event.scenePos()
00167
00168 if event.button() == Qt.LeftButton:
00169 self.mousedown = True
00170
00171 if event.button() == Qt.RightButton:
00172 self.rightdown = True
00173
00174 self.setFocus()
00175
00176 def mouseDoubleClickEvent(self, event):
00177 if event.button() == Qt.LeftButton:
00178
00179 self.mousedoubleclick = True
00180 self.setFocus()
00181
00182 def mouseMoveEvent(self, event):
00183 self.mousePosition = event.scenePos()
00184
00185 def mouseReleaseEvent(self, event):
00186 self.mousePosition = event.scenePos()
00187 if event.button() == Qt.LeftButton:
00188 self.mousedown = False
00189 if event.button() == Qt.RightButton:
00190 self.rightdown = False
00191
00192 def keyPressEvent(self, event):
00193 self.keydown = True
00194 self.key = event.text()
00195 self.keycode = event.key()
00196
00197 def keyReleaseEvent(self, event):
00198 self.keydown = False
00199 self.key = event.text()
00200 self.keycode = event.key()
00201
00202 def wheelEvent(self, event):
00203 self.scrollwheel = True
00204 self.wheeldelta = event.delta() / 120.
00205 print 'event delta', event.delta()
00206
00207