nodebox_graphics.py
Go to the documentation of this file.
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         #self.setMouseTracking(True)
00033         #print self.hasMouseTracking()
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: # Search for a direct hit first.
00099             idx = self.zoomLevels.index(zoom)
00100             return idx, True
00101         except ValueError: # Can't find the zoom level, try looking at the indexes.
00102             idx = 0
00103             try:
00104                 while self.zoomLevels[idx] < zoom:
00105                     idx += 1
00106             except KeyError: # End of the list
00107                 idx = len(self.zoomLevels) - 1 # Just return the last index.
00108             return idx, False
00109 
00110     def zoomIn_(self):
00111         idx, direct = self.findNearestZoomIndex(self.zoom)
00112         # Direct hits are perfect, but indirect hits require a bit of help.
00113         # Because of the way indirect hits are calculated, they are already
00114         # rounded up to the upper zoom level; this means we don't need to add 1.
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             # A lot of code just to display the error in the output view.
00150             etype, value, tb = sys.exc_info()
00151             if tb.tb_next is not None:
00152                 tb = tb.tb_next  # skip the frame doing the exec
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)) # TODO: Refactor color
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             #self.mouseDCPosition = event.scenePos()
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 


rcommander
Author(s): Hai Nguyen (haidai@gmail.com)
autogenerated on Thu Nov 28 2013 11:46:34