def __init__(self, parent, rotator=False): qt4.QGraphicsRectItem.__init__(self, parent) if rotator: self.setBrush(qt4.QBrush(setting.settingdb.color('cntrlline'))) self.setRect(-3, -3, 6, 6) else: self.setBrush(qt4.QBrush(setting.settingdb.color('cntrlcorner'))) self.setRect(-5, -5, 10, 10) self.setPen(qt4.QPen(qt4.Qt.NoPen)) self.setFlag(qt4.QGraphicsItem.ItemIsMovable) self.setZValue(3.)
def brushExtFillPath(painter, extbrush, path, ignorehide=False, stroke=None): """Use an BrushExtended settings object to fill a path on painter. If ignorehide is True, ignore the hide setting on the brush object. stroke is an optional QPen for stroking outline of path """ if extbrush.hide and not ignorehide: if stroke is not None: painter.strokePath(path, stroke) return style = extbrush.style if style in _fillcnvt: # standard fill: use Qt styles for painting color = qt4.QColor(extbrush.color) color.setAlphaF((100 - extbrush.transparency) / 100.) brush = qt4.QBrush(color, _fillcnvt[style]) if stroke is None: painter.fillPath(path, brush) else: painter.save() painter.setPen(stroke) painter.setBrush(brush) painter.drawPath(path) painter.restore() elif style in _hatchmap: # fill with hatching if not extbrush.backhide: # background brush color = qt4.QColor(extbrush.backcolor) color.setAlphaF((100 - extbrush.backtransparency) / 100.) brush = qt4.QBrush(color) painter.fillPath(path, brush) color = qt4.QColor(extbrush.color) color.setAlphaF((100 - extbrush.transparency) / 100.) width = extbrush.get('linewidth').convert(painter) lstyle, dashpattern = extbrush.get('linestyle')._linecnvt[ extbrush.linestyle] pen = qt4.QPen(color, width, lstyle) if dashpattern: pen.setDashPattern(dashpattern) # do hatching with spacing spacing = extbrush.get('patternspacing').convert(painter) if spacing > 0: _hatcher(painter, pen, path, spacing, _hatchmap[style]) if stroke is not None: painter.strokePath(path, stroke)
def _errorBarsCurve(style, xmin, xmax, ymin, ymax, xplotter, yplotter, s, painter, clip): """Draw curve around error region.""" if None not in (xmin, xmax, ymin, ymax): # non-filling brush painter.setBrush(qt4.QBrush()) for xp, yp, xmn, ymn, xmx, ymx in itertools.izip( xplotter, yplotter, xmin, ymin, xmax, ymax): # break up curve into four arcs (for asym error bars) # qt geometry means we have to calculate lots # the big numbers are in 1/16 degrees painter.drawArc( qt4.QRectF(xp - (xmx - xp), yp - (yp - ymx), (xmx - xp) * 2, (yp - ymx) * 2), 0, 1440) painter.drawArc( qt4.QRectF(xp - (xp - xmn), yp - (yp - ymx), (xp - xmn) * 2, (yp - ymx) * 2), 1440, 1440) painter.drawArc( qt4.QRectF(xp - (xp - xmn), yp - (ymn - yp), (xp - xmn) * 2, (ymn - yp) * 2), 2880, 1440) painter.drawArc( qt4.QRectF(xp - (xmx - xp), yp - (ymn - yp), (xmx - xp) * 2, (ymn - yp) * 2), 4320, 1440)
def __init__(self, params): """Initialise with widget and boxbounds shape. Rotation is allowed if allowrotate is set """ qt4.QGraphicsRectItem.__init__(self, params.posn[0], params.posn[1], params.dims[0], params.dims[1]) self.params = params self.rotate(params.angle) # initial setup self.setCursor(qt4.Qt.SizeAllCursor) self.setZValue(1.) self.setFlag(qt4.QGraphicsItem.ItemIsMovable) self.setPen(controlLinePen()) self.setBrush(qt4.QBrush()) # create child graphicsitem for each corner self.corners = [_ShapeCorner(self) for i in xrange(4)] self.corners[0].setCursor(qt4.Qt.SizeFDiagCursor) self.corners[1].setCursor(qt4.Qt.SizeBDiagCursor) self.corners[2].setCursor(qt4.Qt.SizeBDiagCursor) self.corners[3].setCursor(qt4.Qt.SizeFDiagCursor) # whether box is allowed to be rotated self.rotator = None if params.allowrotate: self.rotator = _ShapeCorner(self, rotator=True) self.rotator.setCursor(qt4.Qt.CrossCursor) self.updateCorners() self.rotator.setPos(0, -abs(params.dims[1] * 0.5))
def _makeTextFormat(self, cursor, color): fmt = cursor.charFormat() if color is not None: brush = qt4.QBrush(color) fmt.setForeground(brush) else: # use the default foreground color fmt.clearForeground() return fmt
def drawKeySymbol(self, number, painter, x, y, width, height): """Draw the plot symbol and/or line.""" s = self.settings yp = y + height / 2 # draw line if not s.Line.hide: painter.setBrush(qt4.QBrush()) painter.setPen(s.Line.makeQPen(painter)) painter.drawLine(qt4.QPointF(x, yp), qt4.QPointF(x + width, yp))
def __init__(self, parent=None): path = qt4.QPainterPath() path.addRect(-4, -4, 8, 8) path.addRect(-5, -5, 10, 10) path.moveTo(-8, 0) path.lineTo(8, 0) path.moveTo(0, -8) path.lineTo(0, 8) qt4.QGraphicsPathItem.__init__(self, path, parent) self.setBrush(qt4.QBrush(qt4.Qt.black)) self.setFlags(self.flags() | qt4.QGraphicsItem.ItemIsFocusable)
def draw(self, parentposn, painthelper, outerbounds=None): """Draw the function.""" posn = GenericPlotter.draw(self, parentposn, painthelper, outerbounds=outerbounds) x1, y1, x2, y2 = posn s = self.settings # exit if hidden or function blank if s.hide or s.function.strip() == '': return # get axes widgets axes = self.parent.getAxes((s.xAxis, s.yAxis)) # return if there's no proper axes if (None in axes or axes[0].settings.direction != 'horizontal' or axes[1].settings.direction != 'vertical'): return # clip data within bounds of plotter cliprect = self.clipAxesBounds(axes, posn) painter = painthelper.painter(self, posn, clip=cliprect) # get the points to plot by evaluating the function (xpts, ypts), (pxpts, pypts) = self.calcFunctionPoints(axes, posn) # draw the function line if pxpts is None or pypts is None: # not sure how to deal with errors here painter.setPen(setting.settingdb.color('error')) f = qt4.QFont() f.setPointSize(20) painter.setFont(f) painter.drawText(qt4.QRectF(x1, y1, x2 - x1, y2 - y1), qt4.Qt.AlignCenter, "Cannot evaluate '%s'" % s.function) else: if not s.FillBelow.hide: self._fillRegion(painter, pxpts, pypts, posn, True, cliprect, s.FillBelow) if not s.FillAbove.hide: self._fillRegion(painter, pxpts, pypts, posn, False, cliprect, s.FillAbove) if not s.Line.hide: painter.setBrush(qt4.QBrush()) painter.setPen(s.Line.makeQPen(painter)) self._plotLine(painter, pxpts, pypts, posn, cliprect)
def _errorBarsDiamond(style, xmin, xmax, ymin, ymax, xplotter, yplotter, s, painter, clip): """Draw diamond around error region.""" if None not in (xmin, xmax, ymin, ymax): # expand clip by pen width (urgh) pw = painter.pen().widthF() * 2 clip = qt4.QRectF(qt4.QPointF(clip.left() - pw, clip.top() - pw), qt4.QPointF(clip.right() + pw, clip.bottom() + pw)) path = qt4.QPainterPath() utils.addNumpyPolygonToPath(path, clip, xmin, yplotter, xplotter, ymax, xmax, yplotter, xplotter, ymin) painter.setBrush(qt4.QBrush()) painter.drawPath(path)
def render(self, state): initx = state.x # draw material under bar Part.render(self, state) # draw circle over text with 1pt radius painter = state.painter height = state.fontMetrics().ascent() painter.save() circsize = state.getPixelsPerPt() painter.setBrush(qt4.QBrush(painter.pen().color())) painter.setPen(qt4.QPen(qt4.Qt.NoPen)) x = 0.5 * (initx + state.x) y = state.y - height + circsize painter.drawEllipse( qt4.QRectF(qt4.QPointF(x - circsize, y - circsize), qt4.QPointF(x + circsize, y + circsize))) painter.restore()
def begin(self, paintdevice): """Start painting.""" self.device = paintdevice self.pen = qt4.QPen() self.brush = qt4.QBrush() self.clippath = None self.clipnum = 0 self.existingclips = {} self.matrix = qt4.QMatrix() # svg root element for qt defaults self.rootelement = SVGElement( None, 'svg', ('width="%spx" height="%spx" version="1.1"\n' ' xmlns="http://www.w3.org/2000/svg"\n' ' xmlns:xlink="http://www.w3.org/1999/xlink"') % (fltStr( self.width * dpi * scale), fltStr(self.height * dpi * scale))) SVGElement(self.rootelement, 'desc', '', 'Veusz output document') # definitions, for clips, etc. self.defs = SVGElement(self.rootelement, 'defs', '') # this is where all the drawing goes self.celement = SVGElement( self.rootelement, 'g', 'stroke-linejoin="bevel" stroke-linecap="square" ' 'stroke="#000000" fill-rule="evenodd"') # previous transform, stroke and clip states self.oldstate = [None, None, None] # cache paths to avoid duplication self.pathcache = {} self.pathcacheidx = 0 return True
def draw(self, parentposn, phelper, outerbounds = None): '''Update the margins before drawing.''' s = self.settings # exit if hidden if s.hide: return # get height of label font bounds = self.computeBounds(parentposn, phelper) painter = phelper.painter(self, parentposn) font = s.get('Label').makeQFont(phelper) painter.setFont(font) fontheight = utils.FontMetrics(font, painter.device()).height() horz = s.direction == 'horizontal' # use above to estimate width and height if necessary w = s.get('width') if w.isAuto(): if horz: totalwidth = bounds[2] - bounds[0] - 2*fontheight else: totalwidth = fontheight else: totalwidth = w.convert(painter) h = s.get('height') if h.isAuto(): if horz: totalheight = fontheight else: totalheight = bounds[3] - bounds[1] - 2*fontheight else: totalheight = h.convert(painter) # work out horizontal position h = s.horzPosn if h == 'left': bounds[0] += fontheight bounds[2] = bounds[0] + totalwidth elif h == 'right': bounds[2] -= fontheight bounds[0] = bounds[2] - totalwidth elif h == 'centre': delta = (bounds[2]-bounds[0]-totalwidth)/2. bounds[0] += delta bounds[2] -= delta elif h == 'manual': bounds[0] += (bounds[2]-bounds[0])*s.horzManual bounds[2] = bounds[0] + totalwidth # work out vertical position v = s.vertPosn if v == 'top': bounds[1] += fontheight bounds[3] = bounds[1] + totalheight elif v == 'bottom': bounds[3] -= fontheight bounds[1] = bounds[3] - totalheight elif v == 'centre': delta = (bounds[3]-bounds[1]-totalheight)/2. bounds[1] += delta bounds[3] -= delta elif v == 'manual': bounds[1] += (bounds[3]-bounds[1])*s.vertManual bounds[3] = bounds[1] + totalheight # this is ugly - update bounds in helper state phelper.states[self].bounds = bounds # do no painting if hidden or no image imgwidget = s.get('widgetName').findWidget() if s.hide: return bounds # update image if necessary with new settings if imgwidget is not None: # could find widget (minval, maxval, axisscale, img) = imgwidget.makeColorbarImage(s.direction) else: # couldn't find widget minval, maxval, axisscale = 0., 1., 'linear' img = None self.setAutoRange([minval, maxval]) s.get('log').setSilent(axisscale == 'log') # now draw image on axis... minpix, maxpix = self.graphToPlotterCoords( bounds, N.array([minval, maxval]) ) if s.direction == 'horizontal': c = [ minpix, bounds[1], maxpix, bounds[3] ] else: c = [ bounds[0], maxpix, bounds[2], minpix ] r = qt4.QRectF(c[0], c[1], c[2]-c[0], c[3]-c[1]) # really draw the img if img is not None: painter.drawImage(r, img) # if there's a border if not s.Border.hide: painter.setPen( s.get('Border').makeQPen(painter) ) painter.setBrush( qt4.QBrush() ) painter.drawRect( qt4.QRectF(bounds[0], bounds[1], bounds[2]-bounds[0], bounds[3]-bounds[1]) ) # actually draw axis # we have to force position to full, as otherwise computeBounds # will mess up range if called twice savedposition = self.position self.position = (0., 0., 1., 1.) axis.Axis.draw(self, bounds, phelper, outerbounds=outerbounds, useexistingpainter=painter) self.position = savedposition
def makeQBrushWHide(self): """Make a brush, taking account of hide attribute.""" if self.hide: return qt4.QBrush() else: return self.makeQBrush()
def makeQBrush(self): '''Make a qbrush from the settings.''' color = qt4.QColor(self.color) color.setAlphaF((100 - self.transparency) / 100.) return qt4.QBrush(color, self.get('style').qtStyle())
def draw(self, parentposn, phelper, outerbounds=None): """Plot the data on a plotter.""" posn = GenericPlotter.draw(self, parentposn, phelper, outerbounds=outerbounds) x1, y1, x2, y2 = posn s = self.settings # exit if hidden if s.hide: return # get data doc = self.document xv = s.get('xData').getData(doc) yv = s.get('yData').getData(doc) text = s.get('labels').getData(doc, checknull=True) scalepoints = s.get('scalePoints').getData(doc) colorpoints = s.Color.get('points').getData(doc) # if a missing dataset, make a fake dataset for the second one # based on a row number if xv and not yv and s.get('yData').isEmpty(): # use index for y data length = xv.data.shape[0] yv = document.DatasetRange(length, (1, length)) elif yv and not xv and s.get('xData').isEmpty(): # use index for x data length = yv.data.shape[0] xv = document.DatasetRange(length, (1, length)) if not xv or not yv: # no valid dataset, so exit return # if text entered, then multiply up to get same number of values # as datapoints if text: length = min(len(xv.data), len(yv.data)) text = text * (length / len(text)) + text[:length % len(text)] # get axes widgets axes = self._fetchAxes() if not axes: # no valid axes, so exit return # clip data within bounds of plotter cliprect = self.clipAxesBounds(axes, posn) painter = phelper.painter(self, posn, clip=cliprect) # loop over chopped up values for xvals, yvals, tvals, ptvals, cvals in ( document.generateValidDatasetParts(xv, yv, text, scalepoints, colorpoints)): #print "Calculating coordinates" # calc plotter coords of x and y points xplotter = axes[0].dataToPlotterCoords(posn, xvals.data) yplotter = axes[1].dataToPlotterCoords(posn, yvals.data) #print "Painting plot line" # plot data line (and/or filling above or below) if not s.PlotLine.hide or not s.FillAbove.hide or not s.FillBelow.hide: if s.PlotLine.bezierJoin and hasqtloops: self._drawBezierLine(painter, xplotter, yplotter, posn, xvals, yvals) else: self._drawPlotLine(painter, xplotter, yplotter, posn, xvals, yvals, cliprect) # shift points if in certain step modes if s.PlotLine.steps != 'off': steps = s.PlotLine.steps if s.PlotLine.steps == 'right-shift-points': xplotter[1:] = 0.5 * (xplotter[:-1] + xplotter[1:]) elif s.PlotLine.steps == 'left-shift-points': xplotter[:-1] = 0.5 * (xplotter[:-1] + xplotter[1:]) #print "Painting error bars" # plot errors bars self._plotErrors(posn, painter, xplotter, yplotter, axes, xvals, yvals, cliprect) # plot the points (we do this last so they are on top) markersize = s.get('markerSize').convert(painter) if not s.MarkerLine.hide or not s.MarkerFill.hide: #print "Painting marker fill" if not s.MarkerFill.hide: # filling for markers painter.setBrush(s.MarkerFill.makeQBrush()) else: # no-filling brush painter.setBrush(qt4.QBrush()) #print "Painting marker lines" if not s.MarkerLine.hide: # edges of markers painter.setPen(s.MarkerLine.makeQPen(painter)) else: # invisible pen painter.setPen(qt4.QPen(qt4.Qt.NoPen)) # thin datapoints as required if s.thinfactor <= 1: xplt, yplt = xplotter, yplotter else: xplt, yplt = (xplotter[::s.thinfactor], yplotter[::s.thinfactor]) # whether to scale markers scaling = colorvals = cmap = None if ptvals: scaling = ptvals.data if s.thinfactor > 1: scaling = scaling[::s.thinfactor] # color point individually if cvals: colorvals = utils.applyScaling(cvals.data, s.Color.scaling, s.Color.min, s.Color.max) if s.thinfactor > 1: colorvals = colorvals[::s.thinfactor] cmap = self.document.getColormap( s.MarkerFill.colorMap, s.MarkerFill.colorMapInvert) # actually plot datapoints utils.plotMarkers(painter, xplt, yplt, s.marker, markersize, scaling=scaling, clip=cliprect, cmap=cmap, colorvals=colorvals) # finally plot any labels if tvals and not s.Label.hide: self.drawLabels(painter, xplotter, yplotter, tvals, markersize)
def _errorBarsBox(style, xmin, xmax, ymin, ymax, xplotter, yplotter, s, painter, clip): """Draw box around error region.""" if None not in (xmin, xmax, ymin, ymax): painter.setBrush(qt4.QBrush()) utils.plotBoxesToPainter(painter, xmin, ymin, xmax, ymax, clip)
try: self.checker.check(s.function, s.variable) except RuntimeError, e: self.logEvalError(e) return x1, y1, x2, y2 = posn cliprect = qt4.QRectF( qt4.QPointF(x1, y1), qt4.QPointF(x2, y2) ) painter = phelper.painter(self, posn) self.parent.setClip(painter, posn) apts, bpts = self.getFunctionPoints() px, py = self.parent.graphToPlotCoords(apts, bpts) # plot line painter.setBrush(qt4.QBrush()) painter.setPen( s.PlotLine.makeQPenWHide(painter) ) for x, y in utils.validLinePoints(px, py): if not s.Fill1.hide: self.parent.drawFillPts(painter, s.Fill1, cliprect, x, y) if not s.Fill2.hide: self.parent.drawFillPts(painter, s.Fill2, cliprect, x, y) if not s.PlotLine.hide: p = qt4.QPolygonF() utils.addNumpyToPolygonF(p, x, y) painter.setBrush(qt4.QBrush()) painter.setPen( s.PlotLine.makeQPen(painter) ) utils.plotClippedPolyline(painter, cliprect, p) document.thefactory.register( NonOrthFunction )
def drawAxes(self, painter, bounds, datarange, outerbounds=None): '''Plot axes.''' s = self.settings t = s.Tick if self._maxradius <= 0.: self._maxradius = 1. atick = AxisTicks(0, self._maxradius, t.number, t.number * 4, extendmin=False, extendmax=False) atick.getTicks() majtick = atick.tickvals # draw ticks as circles if not t.hideannuli: painter.setPen(s.Tick.makeQPenWHide(painter)) painter.setBrush(qt4.QBrush()) for tick in majtick[1:]: radius = tick / self._maxradius painter.drawEllipse( qt4.QRectF( qt4.QPointF(self._xc - radius * self._xscale, self._yc - radius * self._yscale), qt4.QPointF(self._xc + radius * self._xscale, self._yc + radius * self._yscale))) # setup axes plot tl = s.TickLabels scale, format = tl.scale, tl.format if format == 'Auto': format = atick.autoformat painter.setPen(tl.makeQPen()) font = tl.makeQFont(painter) # draw radial axis if not s.TickLabels.hideradial: for tick in majtick[1:]: num = utils.formatNumber(tick * scale, format, locale=self.document.locale) x = tick / self._maxradius * self._xscale + self._xc r = utils.Renderer(painter, font, x, self._yc, num, alignhorz=-1, alignvert=-1, usefullheight=True) r.render() if s.units == 'degrees': angles = [ u'0°', u'30°', u'60°', u'90°', u'120°', u'150°', u'180°', u'210°', u'240°', u'270°', u'300°', u'330°' ] else: angles = [ '0', u'π/6', u'π/3', u'π/2', u'2π/3', u'5π/6', u'π', u'7π/6', u'4π/3', u'3π/2', u'5π/3', u'11π/6' ] align = [(-1, 1), (-1, 1), (-1, 1), (0, 1), (1, 1), (1, 1), (1, 0), (1, -1), (1, -1), (0, -1), (-1, -1), (-1, -1)] if s.direction == 'anticlockwise': angles = angles[0:1] + angles[1:][::-1] # rotate labels if zero not at right if s.position0 == 'top': angles = angles[3:] + angles[:4] elif s.position0 == 'left': angles = angles[6:] + angles[:7] elif s.position0 == 'bottom': angles = angles[9:] + angles[:10] # draw labels around plot if not s.TickLabels.hidetangential: for i in xrange(12): angle = 2 * N.pi / 12 x = self._xc + N.cos(angle * i) * self._xscale y = self._yc + N.sin(angle * i) * self._yscale r = utils.Renderer(painter, font, x, y, angles[i], alignhorz=align[i][0], alignvert=align[i][1], usefullheight=True) r.render() # draw spokes if not t.hidespokes: painter.setPen(s.Tick.makeQPenWHide(painter)) painter.setBrush(qt4.QBrush()) angle = 2 * N.pi / 12 lines = [] for i in xrange(12): x = self._xc + N.cos(angle * i) * self._xscale y = self._yc + N.sin(angle * i) * self._yscale lines.append( qt4.QLineF(qt4.QPointF(self._xc, self._yc), qt4.QPointF(x, y))) painter.drawLines(lines)
def draw(self, posn, phelper, outerbounds = None): """Plot the key on a plotter.""" s = self.settings d = self.document if s.hide: return # if a dataset is used, we can't use control items isnotdataset = ( not s.get('xPos').isDataset(d) and not s.get('yPos').isDataset(d) ) if s.mode == 'length-angle': isnotdataset = ( isnotdataset and not s.get('length').isDataset(d) and not s.get('angle').isDataset(d) ) else: isnotdataset = ( isnotdataset and not s.get('xPos2').isDataset(d) and not s.get('yPos2').isDataset(d) ) # now do the drawing clip = None if s.clip: clip = qt4.QRectF( qt4.QPointF(posn[0], posn[1]), qt4.QPointF(posn[2], posn[3]) ) painter = phelper.painter(self, posn, clip=clip) # adjustable positions for the lines arrowsize = s.get('arrowSize').convert(painter) # drawing settings for line if not s.Line.hide: painter.setPen( s.get('Line').makeQPen(painter) ) else: painter.setPen( qt4.QPen(qt4.Qt.NoPen) ) # settings for fill if not s.Fill.hide: painter.setBrush( s.get('Fill').makeQBrush() ) else: painter.setBrush( qt4.QBrush() ) # iterate over positions scaling = posn[2]-posn[0] if s.mode == 'length-angle': lines = self._computeLinesLengthAngle(posn, scaling) else: lines = self._computeLinesPointToPoint(posn) if lines is None: return controlgraphitems = [] for index, (x, y, l, a) in enumerate(lines): utils.plotLineArrow(painter, x, y, l, a, arrowsize=arrowsize, arrowleft=s.arrowleft, arrowright=s.arrowright) if isnotdataset: cgi = controlgraph.ControlLine( self, x, y, x + l*math.cos(a/180.*math.pi), y + l*math.sin(a/180.*math.pi)) cgi.index = index cgi.widgetposn = posn controlgraphitems.append(cgi) phelper.setControlGraph(self, controlgraphitems)