def __init__(self, parent): QtGui.QWidget.__init__(self, parent) self.ui = Ui_ReportGraphicsView() self.ui.setupUi(self) self.dataPoints = [] self.extraData = [] self.dataFormatter = [] self.markingData = [] self.maxXCoord = 0 self.dpFilter = [] self.connect(self.ui.slider_minDP, QtCore.SIGNAL('valueChanged (int)'), self._onMinDpSliderChanged) self.connect(self.ui.slider_maxDP, QtCore.SIGNAL('valueChanged (int)'), self._onMaxDpSliderChanged) self.connect(self.ui.pushButton_zoomIn, QtCore.SIGNAL('clicked()'), self.zoomIn) self.connect(self.ui.pushButton_zoomOut, QtCore.SIGNAL('clicked()'), self.zoomOut) self.connect(self.ui.checkBox_highlightNegative, QtCore.SIGNAL('stateChanged (int)'), self.onHighlightNegativeChanged) self.connect(self.ui.checkBox_showMarkings, QtCore.SIGNAL('stateChanged(int)'), self.onShowMarkingsChanged) self.connect(self.ui.checkBox_filterActivated, QtCore.SIGNAL('stateChanged(int)'), self.onFilterActivatedChanged)
class ReportGraphicsViewWidget(QtGui.QWidget): def __init__(self, parent): QtGui.QWidget.__init__(self, parent) self.ui = Ui_ReportGraphicsView() self.ui.setupUi(self) self.dataPoints = [] self.extraData = [] self.dataFormatter = [] self.markingData = [] self.maxXCoord = 0 self.dpFilter = [] self.colors = {} self.connect(self.ui.slider_minDP, QtCore.SIGNAL('valueChanged (int)'), self._onMinDpSliderChanged) self.connect(self.ui.slider_maxDP, QtCore.SIGNAL('valueChanged (int)'), self._onMaxDpSliderChanged) self.connect(self.ui.pushButton_zoomIn, QtCore.SIGNAL('clicked()'), self.zoomIn) self.connect(self.ui.pushButton_zoomOut, QtCore.SIGNAL('clicked()'), self.zoomOut) self.connect(self.ui.checkBox_highlightNegative, QtCore.SIGNAL('stateChanged (int)'), self.onHighlightNegativeChanged) self.connect(self.ui.checkBox_showMarkings, QtCore.SIGNAL('stateChanged(int)'), self.onShowMarkingsChanged) self.connect(self.ui.checkBox_filterActivated, QtCore.SIGNAL('stateChanged(int)'), self.onFilterActivatedChanged) def setDatapoints(self, dp = None): #print 'ReportWidget:setDatapoints', dp if dp is None: dp = {} self.dataPoints = dp self.ui.slider_minDP.setMaximum(len(dp)) self.ui.slider_maxDP.setMaximum(len(dp)) self.ui.spinBox_minDP.setMaximum(len(dp)) self.ui.spinBox_maxDP.setMaximum(len(dp)) self.ui.slider_maxDP.setValue(len(dp)) def plot(self): gv = self.ui.graphicsView scene = QtGui.QGraphicsScene(gv) scene.setItemIndexMethod(QtGui.QGraphicsScene.NoIndex) maxY = 0 dp = self.filterDp() #for x in dp: for x in range(len(dp)): for y in dp[x]: if maxY < dp[x][y]: maxY = dp[x][y] if maxY != 0: yScalingFactor = 10**(4/maxY) #this makes reports with small y values more readable else: yScalingFactor = 1 oldCoords = {} min_ = self.ui.slider_minDP.value() max_ = self.ui.slider_maxDP.value() currScaling = self.getCurrentScaling() highlightNegative = self.ui.checkBox_highlightNegative.isChecked() self.maxXCoord = 0 for x in range(len(dp)): if x >= min_ and x <= max_: for y in dp[x]: if y not in self.colors.keys(): self.colors[y] = QtGui.QColor(random.randint(0,255), random.randint(0,255),random.randint(0,255)) color = self.colors[y] pen = QtGui.QPen(color) coords = (LEGENDWIDTH+x*200, (maxY - dp[x][y])*yScalingFactor) if self.maxXCoord < coords[0]: self.maxXCoord = coords[0] #print y, x, dp[x][y] rect = Rect(self.dataFormatter, QtCore.QRectF(coords[0], coords[1], 5*currScaling[0], 5*currScaling[1])) rect.setPen(pen) rect.setBrush(color) rect.setAcceptHoverEvents(True) #rect.setZValue(100) rect.setSeriesId(y) rect.setData([y, x, dp[x][y]]) try: rect.setExtraData(self.extraData[x][y]) except (IndexError, KeyError): pass scene.addItem(rect) if highlightNegative and dp[x][y]<0: triangle = QtGui.QGraphicsPolygonItem(QtGui.QPolygonF([QtCore.QPointF(coords[0], coords[1]+10*currScaling[1]), QtCore.QPointF(coords[0]+5*currScaling[0], coords[1]+(10+10)*currScaling[1]), QtCore.QPointF(coords[0]-5*currScaling[0], coords[1]+(10+10)*currScaling[1]), QtCore.QPointF(coords[0], coords[1]+10*currScaling[1])])) triangle.setPen(pen) scene.addItem(triangle) if y in oldCoords: scene.addLine(oldCoords[y][0], oldCoords[y][1], coords[0]+5, coords[1]+5, pen) oldCoords[y] = (coords[0]+5, coords[1]+5) width = scene.width()+50 scene.addLine(LEGENDWIDTH, maxY*yScalingFactor, width, maxY*yScalingFactor) #x-axis scene.addLine(LEGENDWIDTH, 0, LEGENDWIDTH, maxY*yScalingFactor) #y-axis #horizontal guides """pen = QtGui.QPen(QtGui.QColor(200, 200, 200)) for i in range(0, int(max), 100): scene.addLine(LEGENDWIDTH-10, max-i, width, max-i, pen) text = scene.addText(str(i)) text.setPos(LEGENDWIDTH-50, max-i)""" gv.setScene(scene) gv.setCacheMode(QtGui.QGraphicsView.CacheBackground) gv.setRenderHint(QtGui.QPainter.Antialiasing) #gv.setTransformationAnchor(QtGui.QGraphicsView.AnchorUnderMouse) #gv.setResizeAnchor(QtGui.QGraphicsView.AnchorViewCenter) self.updateMarking() def getCurrentScaling(self): try: gvMatrix = self.ui.graphicsView.scene().views()[0].matrix() currScaling = (1/gvMatrix.m11(), 1/gvMatrix.m22()) except (IndexError, AttributeError): currScaling = (1.0, 1.0) return currScaling def setDataFormatter(self, f): self.dataFormatter = f def setExtraData(self, data): self.extraData = data def setMarkingData(self, markingData): self.markingData = markingData def zoomIn(self): self.ui.graphicsView.scale(ZOOMINFACTOR, ZOOMINFACTOR) self.plot() def zoomOut(self): self.ui.graphicsView.scale(ZOOMOUTFACTOR, ZOOMOUTFACTOR) self.plot() def _onMinDpSliderChanged(self, newVal): max_ = self.ui.slider_maxDP.value() if max_ < newVal: self.ui.slider_maxDP.setValue(newVal) self.plot() def _onMaxDpSliderChanged(self, newVal): min_ = self.ui.slider_minDP.value() if min_ > newVal: self.ui.slider_minDP.setValue(newVal) self.plot() def onHighlightNegativeChanged(self, state): self.plot() def onShowMarkingsChanged(self, state): self.plot() def updateMarking(self): if self.ui.checkBox_showMarkings.isChecked(): scene = self.ui.graphicsView.scene() currScaling = self.getCurrentScaling() textGapFactor = math.floor(currScaling[0]/12)+1 coords = (0,scene.height()) #width = scene.width() width = self.maxXCoord #rect = QtGui.QGraphicsRectItem(QtCore.QRectF(coords[0]+LEGENDWIDTH, coords[1], width-(LEGENDWIDTH), 50*currScaling[1])) color = QtGui.QColor(0xdd, 0xdd, 0xdd) pen = QtGui.QPen(color) #scene.addItem(rect) for x in range(len(self.dataPoints)): if x%textGapFactor == 0: dpCoords = (LEGENDWIDTH+x*200,coords[1]) scene.addLine(dpCoords[0], dpCoords[1]-150*currScaling[1], dpCoords[0], dpCoords[1]-100*currScaling[1], pen) textItem = QtGui.QGraphicsTextItem() textItem.setPos(dpCoords[0]-15*currScaling[0],dpCoords[1]) try: text = self.markingData[x] except IndexError: text = x textItem.setPlainText(unicode(text)) textItem.rotate(270) textItem.setScale(currScaling[0]) scene.addItem(textItem) def onlyShowSeries(self, seriesId): self.dpFilter.append(seriesId) cb = self.ui.checkBox_filterActivated cb.setChecked(QtCore.Qt.Checked) cb.setEnabled(True) self.plot() def showAllSeries(self): self.dpFilter = [] cb = self.ui.checkBox_filterActivated cb.setChecked(QtCore.Qt.Unchecked) cb.setEnabled(False) self.plot() def filterDp(self): if len(self.dpFilter) > 0: dp = [] for f in self.dpFilter: for x in range(len(self.dataPoints)): dp.append({}) for y in self.dataPoints[x]: if y in f: dp[x][y] = self.dataPoints[x][y] return dp else: return copy.deepcopy(self.dataPoints) def onFilterActivatedChanged(self, state): if len(self.dpFilter) > 0 and state == QtCore.Qt.Unchecked: self.showAllSeries() def getColor(self, key): return self.colors[key]