def getAdjustedText(self, text): font = QFont('Verdana', 8) fm = QFontMetricsF(font) w = fm.width(text) if w < self.BOX_WIDTH - 25 - FlatButtonGraphicItem.WIDTH: return text text = text[0:-3] + '...' w = fm.width(text) while w > self.BOX_WIDTH - 25 - FlatButtonGraphicItem.WIDTH: text = text[0:-4] + '...' w = fm.width(text) return text
def getLinkPointForParameter(self, paramIndex): offsetX = 25 if isinstance(self.element, Algorithm) and self.element.paramsFolded: paramIndex = -1 offsetX = 17 font = QFont('Verdana', 8) fm = QFontMetricsF(font) if isinstance(self.element, Algorithm): h = -(fm.height() * 1.2) * (paramIndex + 2) - fm.height() / 2.0 + 8 h = h - ModelerGraphicItem.BOX_HEIGHT / 2.0 else: h = 0 return QPointF(-ModelerGraphicItem.BOX_WIDTH / 2 + offsetX, h)
def getLinkPointForOutput(self, outputIndex): if isinstance(self.element, Algorithm) and self.element.algorithm.outputs: outputIndex = (outputIndex if not self.element.outputsFolded else -1) text = self.getAdjustedText(self.element.algorithm.outputs[outputIndex].description) font = QFont('Verdana', 8) fm = QFontMetricsF(font) w = fm.width(text) h = fm.height() * 1.2 * (outputIndex + 1) + fm.height() / 2.0 y = h + ModelerGraphicItem.BOX_HEIGHT / 2.0 + 5 x = (-ModelerGraphicItem.BOX_WIDTH / 2 + 33 + w + 5 if not self.element.outputsFolded else 10) return QPointF(x, y) else: return QPointF(0, 0)
def boundingRect(self): font = QFont('Verdana', 8) fm = QFontMetricsF(font) unfolded = isinstance(self.element, Algorithm) and not self.element.paramsFolded numParams = len(self.element.algorithm.parameters) if unfolded else 0 unfolded = isinstance(self.element, Algorithm) and not self.element.outputsFolded numOutputs = len(self.element.algorithm.outputs) if unfolded else 0 hUp = fm.height() * 1.2 * (numParams + 2) hDown = fm.height() * 1.2 * (numOutputs + 2) rect = QRectF(-(ModelerGraphicItem.BOX_WIDTH + 2) / 2, -(ModelerGraphicItem.BOX_HEIGHT + 2) / 2 - hUp, ModelerGraphicItem.BOX_WIDTH + 2, ModelerGraphicItem.BOX_HEIGHT + hDown + hUp) return rect
def boundingRect(self): font = QFont('Verdana', 8) font.setPixelSize(12) fm = QFontMetricsF(font) unfolded = isinstance(self.element, QgsProcessingModelChildAlgorithm) and not self.element.parametersCollapsed() numParams = len([a for a in self.element.algorithm().parameterDefinitions() if not a.isDestination()]) if unfolded else 0 unfolded = isinstance(self.element, QgsProcessingModelChildAlgorithm) and not self.element.outputsCollapsed() numOutputs = len(self.element.algorithm().outputDefinitions()) if unfolded else 0 hUp = fm.height() * 1.2 * (numParams + 2) hDown = fm.height() * 1.2 * (numOutputs + 2) rect = QRectF(-(ModelerGraphicItem.BOX_WIDTH + 2) / 2, -(ModelerGraphicItem.BOX_HEIGHT + 2) / 2 - hUp, ModelerGraphicItem.BOX_WIDTH + 2, ModelerGraphicItem.BOX_HEIGHT + hDown + hUp) return rect
def getLinkPointForOutput(self, outputIndex): if isinstance(self.element, QgsProcessingModelChildAlgorithm) and self.element.algorithm().outputDefinitions(): outputIndex = (outputIndex if not self.element.outputsCollapsed() else -1) text = self.getAdjustedText(self.element.algorithm().outputDefinitions()[outputIndex].description()) font = QFont('Verdana', 8) font.setPixelSize(12) fm = QFontMetricsF(font) w = fm.width(text) h = fm.height() * 1.2 * (outputIndex + 1) + fm.height() / 2.0 y = h + ModelerGraphicItem.BOX_HEIGHT / 2.0 + 5 x = (-ModelerGraphicItem.BOX_WIDTH / 2 + 33 + w + 5 if not self.element.outputsCollapsed() else 10) return QPointF(x, y) else: return QPointF(0, 0)
def getLinkPointForParameter(self, paramIndex): offsetX = 25 if isinstance(self.element, QgsProcessingModelChildAlgorithm) and self.element.parametersCollapsed(): paramIndex = -1 offsetX = 17 if isinstance(self.element, QgsProcessingModelParameter): paramIndex = -1 offsetX = 0 font = QFont('Verdana', 8) font.setPixelSize(12) fm = QFontMetricsF(font) if isinstance(self.element, QgsProcessingModelChildAlgorithm): h = -(fm.height() * 1.2) * (paramIndex + 2) - fm.height() / 2.0 + 8 h = h - ModelerGraphicItem.BOX_HEIGHT / 2.0 else: h = 0 return QPointF(-ModelerGraphicItem.BOX_WIDTH / 2 + offsetX, h)
def polygon(self): font = QFont('Verdana', 8) fm = QFontMetricsF(font) hUp = fm.height() * 1.2 * (len(self.element.parameters) + 2) hDown = fm.height() * 1.2 * (len(self.element.outputs) + 2) pol = QPolygonF([ QPointF(-(ModelerGraphicItem.BOX_WIDTH + 2) / 2, -(ModelerGraphicItem.BOX_HEIGHT + 2) / 2 - hUp), QPointF(-(ModelerGraphicItem.BOX_WIDTH + 2) / 2, (ModelerGraphicItem.BOX_HEIGHT + 2) / 2 + hDown), QPointF((ModelerGraphicItem.BOX_WIDTH + 2) / 2, (ModelerGraphicItem.BOX_HEIGHT + 2) / 2 + hDown), QPointF((ModelerGraphicItem.BOX_WIDTH + 2) / 2, -(ModelerGraphicItem.BOX_HEIGHT + 2) / 2 - hUp), QPointF(-(ModelerGraphicItem.BOX_WIDTH + 2) / 2, -(ModelerGraphicItem.BOX_HEIGHT + 2) / 2 - hUp) ]) return pol
def getLinkPointForOutput(self, outputIndex): if isinstance(self.element, QgsProcessingModelChildAlgorithm ) and self.element.algorithm().outputDefinitions(): outputIndex = (outputIndex if not self.element.outputsCollapsed() else -1) text = self.getAdjustedText( self.element.algorithm().outputDefinitions() [outputIndex].description()) font = QFont('Verdana', 8) font.setPixelSize(12) fm = QFontMetricsF(font) w = fm.width(text) h = fm.height() * 1.2 * (outputIndex + 1) + fm.height() / 2.0 y = h + ModelerGraphicItem.BOX_HEIGHT / 2.0 + 5 x = (-ModelerGraphicItem.BOX_WIDTH / 2 + 33 + w + 5 if not self.element.outputsCollapsed() else 10) return QPointF(x, y) else: return QPointF(0, 0)
def polygon(self): font = QFont('Verdana', 8) font.setPixelSize(12) fm = QFontMetricsF(font) hUp = fm.height() * 1.2 * (len(self.element.parameters) + 2) hDown = fm.height() * 1.2 * (len(self.element.outputs) + 2) pol = QPolygonF([ QPointF(-(ModelerGraphicItem.BOX_WIDTH + 2) / 2, -(ModelerGraphicItem.BOX_HEIGHT + 2) / 2 - hUp), QPointF(-(ModelerGraphicItem.BOX_WIDTH + 2) / 2, (ModelerGraphicItem.BOX_HEIGHT + 2) / 2 + hDown), QPointF((ModelerGraphicItem.BOX_WIDTH + 2) / 2, (ModelerGraphicItem.BOX_HEIGHT + 2) / 2 + hDown), QPointF((ModelerGraphicItem.BOX_WIDTH + 2) / 2, -(ModelerGraphicItem.BOX_HEIGHT + 2) / 2 - hUp), QPointF(-(ModelerGraphicItem.BOX_WIDTH + 2) / 2, -(ModelerGraphicItem.BOX_HEIGHT + 2) / 2 - hUp) ]) return pol
def paint(self, painter, option, widget=None): rect = QRectF(-(ModelerGraphicItem.BOX_WIDTH + 2) / 2.0, -(ModelerGraphicItem.BOX_HEIGHT + 2) / 2.0, ModelerGraphicItem.BOX_WIDTH + 2, ModelerGraphicItem.BOX_HEIGHT + 2) painter.setPen(QPen(Qt.gray, 1)) color = QColor(125, 232, 232) if isinstance(self.element, ModelerParameter): color = QColor(179, 179, 255) elif isinstance(self.element, Algorithm): color = Qt.white painter.setBrush(QBrush(color, Qt.SolidPattern)) painter.drawRect(rect) font = QFont('Verdana', 8) painter.setFont(font) painter.setPen(QPen(Qt.black)) text = self.getAdjustedText(self.text) if isinstance(self.element, Algorithm) and not self.element.active: painter.setPen(QPen(Qt.gray)) text = text + "\n(deactivated)" elif self.isSelected(): painter.setPen(QPen(Qt.blue)) fm = QFontMetricsF(font) text = self.getAdjustedText(self.text) h = fm.height() pt = QPointF(-ModelerGraphicItem.BOX_WIDTH / 2 + 25, h / 2.0) painter.drawText(pt, text) painter.setPen(QPen(Qt.black)) if isinstance(self.element, Algorithm): h = -(fm.height() * 1.2) h = h - ModelerGraphicItem.BOX_HEIGHT / 2.0 + 5 pt = QPointF(-ModelerGraphicItem.BOX_WIDTH / 2 + 25, h) painter.drawText(pt, 'In') i = 1 if not self.element.paramsFolded: for param in self.element.algorithm.parameters: if not param.hidden: text = self.getAdjustedText(param.description) h = -(fm.height() * 1.2) * (i + 1) h = h - ModelerGraphicItem.BOX_HEIGHT / 2.0 + 5 pt = QPointF(-ModelerGraphicItem.BOX_WIDTH / 2 + 33, h) painter.drawText(pt, text) i += 1 h = fm.height() * 1.2 h = h + ModelerGraphicItem.BOX_HEIGHT / 2.0 pt = QPointF(-ModelerGraphicItem.BOX_WIDTH / 2 + 25, h) painter.drawText(pt, 'Out') if not self.element.outputsFolded: for i, out in enumerate(self.element.algorithm.outputs): text = self.getAdjustedText(out.description) h = fm.height() * 1.2 * (i + 2) h = h + ModelerGraphicItem.BOX_HEIGHT / 2.0 pt = QPointF(-ModelerGraphicItem.BOX_WIDTH / 2 + 33, h) painter.drawText(pt, text) if self.pixmap: painter.drawPixmap(-(ModelerGraphicItem.BOX_WIDTH / 2.0) + 3, -8, self.pixmap)
def getLinkPointForParameter(self, paramIndex): offsetX = 25 if isinstance(self.element, QgsProcessingModelAlgorithm.ChildAlgorithm ) and self.element.parametersCollapsed(): paramIndex = -1 offsetX = 17 if isinstance(self.element, QgsProcessingModelAlgorithm.ModelParameter): paramIndex = -1 offsetX = 0 font = QFont('Verdana', 8) font.setPixelSize(12) fm = QFontMetricsF(font) if isinstance(self.element, QgsProcessingModelAlgorithm.ChildAlgorithm): h = -(fm.height() * 1.2) * (paramIndex + 2) - fm.height() / 2.0 + 8 h = h - ModelerGraphicItem.BOX_HEIGHT / 2.0 else: h = 0 return QPointF(-ModelerGraphicItem.BOX_WIDTH / 2 + offsetX, h)
def newItemAddedToLayout(self, frame): item = frame.multiFrame() item.setMap(None) text = 'Choose the data source of the table and ' \ 'the link columns in the STDM item properties.' table_text = QCoreApplication.translate('StdmItems', text) default_column = QgsLayoutTableColumn(table_text) item.setColumns([default_column]) item.recalculateFrameSizes() fm = QFontMetricsF(item.headerTextFormat().font()) table_width_layout_units = fm.width(text + ' ') size = frame.sizeWithUnits() size.setWidth(item.layout().convertFromLayoutUnits( table_width_layout_units, size.units()).length()) frame.attemptResize(size) # Set ID to match UUID frame.setId(frame.uuid())
def boundingRect(self): font = QFont('Verdana', 8) font.setPixelSize(12) fm = QFontMetricsF(font) unfolded = isinstance(self.element, QgsProcessingModelChildAlgorithm ) and not self.element.parametersCollapsed() numParams = len([ a for a in self.element.algorithm().parameterDefinitions() if not a.isDestination() ]) if unfolded else 0 unfolded = isinstance(self.element, QgsProcessingModelChildAlgorithm ) and not self.element.outputsCollapsed() numOutputs = len( self.element.algorithm().outputDefinitions()) if unfolded else 0 hUp = fm.height() * 1.2 * (numParams + 2) hDown = fm.height() * 1.2 * (numOutputs + 2) rect = QRectF(-(ModelerGraphicItem.BOX_WIDTH + 2) / 2, -(ModelerGraphicItem.BOX_HEIGHT + 2) / 2 - hUp, ModelerGraphicItem.BOX_WIDTH + 2, ModelerGraphicItem.BOX_HEIGHT + hDown + hUp) return rect
def set_symbol(self, symbol_image: QImage): self.pixmap = QPixmap.fromImage(symbol_image) fm = QFontMetricsF(self.marker_font) # set item size self.item_size.setWidth(self.pixmap.width() + fm.width("360")) pixmap_height = self.pixmap.height() font_height = fm.height() if pixmap_height >= font_height: self.item_size.setHeight(self.pixmap.height()) else: self.item_size.setHeight(fm.height()) half_item_width = self.pixmap.width() / 2.0 self.arrow_path = QPainterPath() self.arrow_path.moveTo(half_item_width, pixmap_height) self.arrow_path.lineTo(half_item_width, 0) self.arrow_path.moveTo(self.pixmap.width() * 0.25, pixmap_height * 0.25) self.arrow_path.lineTo(half_item_width, 0) self.arrow_path.lineTo(self.pixmap.width() * 0.75, pixmap_height * 0.25)
def append_CharacterMarkerSymbolLayerAsSvg(symbol, layer, context: Context): # pylint: disable=too-many-locals """ Appends a CharacterMarkerSymbolLayer to a symbol, rendering the font character to an SVG file. """ font_family = layer.font character = chr(layer.unicode) color = symbol_color_to_qcolor(layer.color) angle = convert_angle(layer.angle) font = QFont(font_family) font.setPointSizeF(layer.size) # Using the rect of a painter path gives better results then using font metrics path = QPainterPath() path.setFillRule(Qt.WindingFill) path.addText(0, 0, font, character) rect = path.boundingRect() font_bounding_rect = QFontMetricsF(font).boundingRect(character) # adjust size -- marker size in esri is the font size, svg marker size in qgis is the svg rect size scale = rect.width() / font_bounding_rect.width() gen = QSvgGenerator() svg_path = symbol_name_to_filename(context.symbol_name, context.picture_folder, 'svg') gen.setFileName(svg_path) gen.setViewBox(rect) painter = QPainter(gen) painter.setFont(font) # todo -- size! if context.parameterise_svg: painter.setBrush(QBrush(QColor(255, 0, 0))) else: painter.setBrush(QBrush(color)) painter.setPen(Qt.NoPen) painter.drawPath(path) painter.end() if context.parameterise_svg: with open(svg_path, 'r') as f: t = f.read() t = t.replace('#ff0000', 'param(fill)') t = t.replace('fill-opacity="1" ', 'fill-opacity="param(fill-opacity)"') t = t.replace( 'stroke="none"', 'stroke="param(outline)" stroke-opacity="param(outline-opacity) 1" stroke-width="param(outline-width) 0"' ) with open(svg_path, 'w') as f: f.write(t) svg_path = context.convert_path(svg_path) out = QgsSvgMarkerSymbolLayer(svg_path) out.setSizeUnit(context.units) out.setSize(context.convert_size(scale * rect.width())) out.setAngle(angle) out.setFillColor(color) out.setStrokeWidth(0) out.setEnabled(layer.enabled) out.setLocked(layer.locked) out.setOffset( adjust_offset_for_rotation( QPointF(context.convert_size(layer.x_offset), -context.convert_size(layer.y_offset)), layer.angle)) out.setOffsetUnit(context.units) symbol.appendSymbolLayer(out)
def paint(self, painter, option, widget=None): rect = QRectF(-(ModelerGraphicItem.BOX_WIDTH + 2) / 2.0, -(ModelerGraphicItem.BOX_HEIGHT + 2) / 2.0, ModelerGraphicItem.BOX_WIDTH + 2, ModelerGraphicItem.BOX_HEIGHT + 2) if isinstance(self.element, QgsProcessingModelParameter): color = QColor(238, 242, 131) stroke = QColor(234, 226, 118) selected = QColor(116, 113, 68) elif isinstance(self.element, QgsProcessingModelChildAlgorithm): color = QColor(255, 255, 255) stroke = Qt.gray selected = QColor(50, 50, 50) else: color = QColor(172, 196, 114) stroke = QColor(90, 140, 90) selected = QColor(42, 65, 42) if self.isSelected(): stroke = selected color = color.darker(110) painter.setPen(QPen(stroke, 0)) # 0 width "cosmetic" pen painter.setBrush(QBrush(color, Qt.SolidPattern)) painter.drawRect(rect) font = QFont('Verdana', 8) font.setPixelSize(12) painter.setFont(font) painter.setPen(QPen(Qt.black)) text = self.getAdjustedText(self.text) if isinstance(self.element, QgsProcessingModelChildAlgorithm) and not self.element.isActive(): painter.setPen(QPen(Qt.gray)) text = text + "\n(deactivated)" fm = QFontMetricsF(font) text = self.getAdjustedText(self.text) h = fm.ascent() pt = QPointF(-ModelerGraphicItem.BOX_WIDTH / 2 + 25, ModelerGraphicItem.BOX_HEIGHT / 2.0 - h + 1) painter.drawText(pt, text) painter.setPen(QPen(Qt.black)) if isinstance(self.element, QgsProcessingModelChildAlgorithm): h = -(fm.height() * 1.2) h = h - ModelerGraphicItem.BOX_HEIGHT / 2.0 + 5 pt = QPointF(-ModelerGraphicItem.BOX_WIDTH / 2 + 25, h) painter.drawText(pt, 'In') i = 1 if not self.element.parametersCollapsed(): for param in [p for p in self.element.algorithm().parameterDefinitions() if not p.isDestination()]: if not param.flags() & QgsProcessingParameterDefinition.FlagHidden: text = self.getAdjustedText(param.description()) h = -(fm.height() * 1.2) * (i + 1) h = h - ModelerGraphicItem.BOX_HEIGHT / 2.0 + 5 pt = QPointF(-ModelerGraphicItem.BOX_WIDTH / 2 + 33, h) painter.drawText(pt, text) i += 1 h = fm.height() * 1.1 h = h + ModelerGraphicItem.BOX_HEIGHT / 2.0 pt = QPointF(-ModelerGraphicItem.BOX_WIDTH / 2 + 25, h) painter.drawText(pt, 'Out') if not self.element.outputsCollapsed(): for i, out in enumerate(self.element.algorithm().outputDefinitions()): text = self.getAdjustedText(out.description()) h = fm.height() * 1.2 * (i + 2) h = h + ModelerGraphicItem.BOX_HEIGHT / 2.0 pt = QPointF(-ModelerGraphicItem.BOX_WIDTH / 2 + 33, h) painter.drawText(pt, text) if self.pixmap: painter.drawPixmap(-(ModelerGraphicItem.BOX_WIDTH / 2.0) + 3, -8, self.pixmap) elif self.picture: painter.drawPicture(-(ModelerGraphicItem.BOX_WIDTH / 2.0) + 3, -8, self.picture)
def paint(self, painter, option, widget=None): rect = QRectF(-(ModelerGraphicItem.BOX_WIDTH + 2) / 2.0, -(ModelerGraphicItem.BOX_HEIGHT + 2) / 2.0, ModelerGraphicItem.BOX_WIDTH + 2, ModelerGraphicItem.BOX_HEIGHT + 2) if isinstance(self.element, QgsProcessingModelParameter): color = QColor(238, 242, 131) stroke = QColor(234, 226, 118) selected = QColor(116, 113, 68) elif isinstance(self.element, QgsProcessingModelChildAlgorithm): color = QColor(255, 255, 255) stroke = Qt.gray selected = QColor(50, 50, 50) else: color = QColor(172, 196, 114) stroke = QColor(90, 140, 90) selected = QColor(42, 65, 42) if self.isSelected(): stroke = selected color = color.darker(110) painter.setPen(QPen(stroke, 0)) # 0 width "cosmetic" pen painter.setBrush(QBrush(color, Qt.SolidPattern)) painter.drawRect(rect) font = QFont('Verdana', 8) font.setPixelSize(12) painter.setFont(font) painter.setPen(QPen(Qt.black)) text = self.getAdjustedText(self.text) if isinstance(self.element, QgsProcessingModelChildAlgorithm ) and not self.element.isActive(): painter.setPen(QPen(Qt.gray)) text = text + "\n(deactivated)" fm = QFontMetricsF(font) text = self.getAdjustedText(self.text) h = fm.ascent() pt = QPointF(-ModelerGraphicItem.BOX_WIDTH / 2 + 25, ModelerGraphicItem.BOX_HEIGHT / 2.0 - h + 1) painter.drawText(pt, text) painter.setPen(QPen(Qt.black)) if isinstance(self.element, QgsProcessingModelChildAlgorithm): h = -(fm.height() * 1.2) h = h - ModelerGraphicItem.BOX_HEIGHT / 2.0 + 5 pt = QPointF(-ModelerGraphicItem.BOX_WIDTH / 2 + 25, h) painter.drawText(pt, 'In') i = 1 if not self.element.parametersCollapsed(): for param in [ p for p in self.element.algorithm().parameterDefinitions() if not p.isDestination() ]: if not param.flags( ) & QgsProcessingParameterDefinition.FlagHidden: text = self.getAdjustedText(param.description()) h = -(fm.height() * 1.2) * (i + 1) h = h - ModelerGraphicItem.BOX_HEIGHT / 2.0 + 5 pt = QPointF(-ModelerGraphicItem.BOX_WIDTH / 2 + 33, h) painter.drawText(pt, text) i += 1 h = fm.height() * 1.1 h = h + ModelerGraphicItem.BOX_HEIGHT / 2.0 pt = QPointF(-ModelerGraphicItem.BOX_WIDTH / 2 + 25, h) painter.drawText(pt, 'Out') if not self.element.outputsCollapsed(): for i, out in enumerate( self.element.algorithm().outputDefinitions()): text = self.getAdjustedText(out.description()) h = fm.height() * 1.2 * (i + 2) h = h + ModelerGraphicItem.BOX_HEIGHT / 2.0 pt = QPointF(-ModelerGraphicItem.BOX_WIDTH / 2 + 33, h) painter.drawText(pt, text) if self.pixmap: painter.drawPixmap(-(ModelerGraphicItem.BOX_WIDTH / 2.0) + 3, -8, self.pixmap) elif self.picture: painter.drawPicture(-(ModelerGraphicItem.BOX_WIDTH / 2.0) + 3, -8, self.picture)
def paint(self, painter, option, widget): if not painter: return painter.save() painter.setRenderHint(QPainter.Antialiasing, True) # do a bit of trigonometry to find out how to transform a rotated item such # that the center point is at the point feature x = 0.0 y = 0.0 if self.pixmap.width() > 0 and self.pixmap.height() > 0: half_item_diagonal = math.sqrt( self.pixmap.width() * self.pixmap.width() + self.pixmap.height() * self.pixmap.height()) / 2 diagonal_angle = math.acos( self.pixmap.width() / (half_item_diagonal * 2)) * 180 / math.pi x = half_item_diagonal * math.cos( (self.rotation - diagonal_angle) * math.pi / 180) y = half_item_diagonal * math.sin( (self.rotation - diagonal_angle) * math.pi / 180) painter.rotate(self.rotation) painter.translate(x - self.pixmap.width() / 2.0, -y - self.pixmap.height() / 2.0) painter.drawPixmap(0, 0, self.pixmap) # draw arrow, using a red line over a thicker white line so that the arrow is visible # against a range of backgrounds pen = QPen() pen.setWidth(GuiUtils.scale_icon_size(4)) pen.setColor(QColor(Qt.white)) painter.setPen(pen) painter.drawPath(self.arrow_path) pen.setWidth(GuiUtils.scale_icon_size(1)) pen.setColor(QColor(Qt.red)) painter.setPen(pen) painter.drawPath(self.arrow_path) painter.restore() # draw numeric value beside the symbol painter.save() painter.setRenderHint(QPainter.Antialiasing, True) buffer_pen = QPen() buffer_pen.setColor(Qt.white) buffer_pen.setWidthF(GuiUtils.scale_icon_size(4)) fm = QFontMetricsF(self.marker_font) label = QPainterPath() label.addText(self.pixmap.width(), self.pixmap.height() / 2.0 + fm.height() / 2.0, self.marker_font, str(round(self.rotation, 1))) painter.setPen(buffer_pen) painter.setBrush(Qt.NoBrush) painter.drawPath(label) painter.setPen(Qt.NoPen) painter.setBrush(QBrush(Qt.black)) painter.drawPath(label) painter.restore()