def toQPainterPath(self): """Return a QPainterPath containing all segments of this path. """ if not self.isValid(): raise Path2dException('invalid path') p = QPainterPath() sx, sy = self._elements[0] if len(self._elements[1]) == 2: # Only add a start point if the QPainterPath will start with a # line, not an arc. p.moveTo(sx, sy) for e in self._elements[1:]: if len(e) == 2: p.lineTo(*e) sx, sy = e else: (ex, ey), (cx, cy), arcDir = e r = hypot(ex - cx, ey - cy) d = r * 2 sa = degrees(atan2(sy - cy, sx - cx)) % 360.0 ea = degrees(atan2(ey - cy, ex - cx)) % 360.0 # NOTE: machtool uses a right-handed cartesian coordinate # system with the Y+ up. Because of this, the QRectF # used to define the arc has a negative height. This # makes a positive arc angle sweep cclw as it should. rect = QRectF(cx - r, cy + r, d, -d) if arcDir == 'cclw': span = (ea + 360.0 if ea < sa else ea) - sa else: span = -((sa + 360.0 if sa < ea else sa) - ea) p.arcMoveTo(rect, sa) p.arcTo(rect, sa, span) sx, sy = ex, ey return p
def toQPainterPath(self): """Return a QPainterPath containing all segments of this path. """ if not self.isValid(): raise Path2dException('invalid path') p = QPainterPath() sx, sy = self._elements[0] if len(self._elements[1]) == 2: # Only add a start point if the QPainterPath will start with a # line, not an arc. p.moveTo(sx, sy) for e in self._elements[1:]: if len(e) == 2: p.lineTo(*e) sx, sy = e else: (ex, ey), (cx, cy), arcDir = e r = hypot(ex-cx, ey-cy) d = r*2 sa = degrees(atan2(sy-cy, sx-cx)) % 360.0 ea = degrees(atan2(ey-cy, ex-cx)) % 360.0 # NOTE: machtool uses a right-handed cartesian coordinate # system with the Y+ up. Because of this, the QRectF # used to define the arc has a negative height. This # makes a positive arc angle sweep cclw as it should. rect = QRectF(cx - r, cy + r, d, -d) if arcDir == 'cclw': span = (ea + 360.0 if ea < sa else ea) - sa else: span = -((sa + 360.0 if sa < ea else sa) - ea) p.arcMoveTo(rect, sa) p.arcTo(rect, sa, span) sx, sy = ex, ey return p
def __init__(self, radiusOut, raiusIn, angle, arcLen, parent=None): QGraphicsPathItem.__init__(self, parent=parent) self._radiusOut = radiusOut self._raiusIn = raiusIn self._angle = angle self._arcLen = arcLen self._pen = QPen(QColor('#000000')) self._pen.setWidth(1) self.setPen(self._pen) self._hoverPen = QPen(QColor('#000000')) self._hoverPen.setWidth(2) brush = QBrush(QColor('#FF9966')) self.setBrush(brush) rectOut = QRectF(-radiusOut, -radiusOut, radiusOut*2.0, radiusOut*2.0) rectIn = QRectF(-raiusIn, -raiusIn, raiusIn*2.0, raiusIn*2.0) startAngle = angle - arcLen/2.0 endAngle = angle + arcLen/2.0 path = QPainterPath() path.arcMoveTo(rectIn, startAngle) path.arcTo(rectOut, startAngle, arcLen) path.arcTo(rectIn, endAngle, 0) path.arcTo(rectIn, endAngle, -arcLen) self.setPath(path) self._isHover = False self._ioDragFirstPos = None
def setupGraphics(self): """ Set up the graphics. """ shape_rect = QRectF(-24, -24, 48, 48) self.shapeItem = NodeBodyItem(self) self.shapeItem.setShapeRect(shape_rect) self.shapeItem.setAnimationEnabled(self.__animationEnabled) # Rect for widget's 'ears'. anchor_rect = QRectF(-31, -31, 62, 62) self.inputAnchorItem = SinkAnchorItem(self) input_path = QPainterPath() start_angle = 180 - self.ANCHOR_SPAN_ANGLE / 2 input_path.arcMoveTo(anchor_rect, start_angle) input_path.arcTo(anchor_rect, start_angle, self.ANCHOR_SPAN_ANGLE) self.inputAnchorItem.setAnchorPath(input_path) self.outputAnchorItem = SourceAnchorItem(self) output_path = QPainterPath() start_angle = self.ANCHOR_SPAN_ANGLE / 2 output_path.arcMoveTo(anchor_rect, start_angle) output_path.arcTo(anchor_rect, start_angle, -self.ANCHOR_SPAN_ANGLE) self.outputAnchorItem.setAnchorPath(output_path) self.inputAnchorItem.hide() self.outputAnchorItem.hide() # Title caption item self.captionTextItem = NameTextItem(self) self.captionTextItem.setPlainText("") self.captionTextItem.setPos(0, 33) def iconItem(standard_pixmap): item = GraphicsIconItem(self, icon=standard_icon(standard_pixmap), iconSize=QSize(16, 16)) item.hide() return item self.errorItem = iconItem(QStyle.SP_MessageBoxCritical) self.warningItem = iconItem(QStyle.SP_MessageBoxWarning) self.infoItem = iconItem(QStyle.SP_MessageBoxInformation) self.prepareGeometryChange() self.__boundingRect = None
def setupGraphics(self): """ Set up the graphics. """ shape_rect = QRectF(-24, -24, 48, 48) self.shapeItem = NodeBodyItem(self) self.shapeItem.setShapeRect(shape_rect) self.shapeItem.setAnimationEnabled(self.__animationEnabled) # Rect for widget's 'ears'. anchor_rect = QRectF(-31, -31, 62, 62) self.inputAnchorItem = SinkAnchorItem(self) input_path = QPainterPath() start_angle = 180 - self.ANCHOR_SPAN_ANGLE / 2 input_path.arcMoveTo(anchor_rect, start_angle) input_path.arcTo(anchor_rect, start_angle, self.ANCHOR_SPAN_ANGLE) self.inputAnchorItem.setAnchorPath(input_path) self.outputAnchorItem = SourceAnchorItem(self) output_path = QPainterPath() start_angle = self.ANCHOR_SPAN_ANGLE / 2 output_path.arcMoveTo(anchor_rect, start_angle) output_path.arcTo(anchor_rect, start_angle, - self.ANCHOR_SPAN_ANGLE) self.outputAnchorItem.setAnchorPath(output_path) self.inputAnchorItem.hide() self.outputAnchorItem.hide() # Title caption item self.captionTextItem = NameTextItem(self) self.captionTextItem.setPlainText("") self.captionTextItem.setPos(0, 33) def iconItem(standard_pixmap): item = GraphicsIconItem(self, icon=standard_icon(standard_pixmap), iconSize=QSize(16, 16)) item.hide() return item self.errorItem = iconItem(QStyle.SP_MessageBoxCritical) self.warningItem = iconItem(QStyle.SP_MessageBoxWarning) self.infoItem = iconItem(QStyle.SP_MessageBoxInformation) self.prepareGeometryChange() self.__boundingRect = None
def _generate_popup_path(rect, xRadius, yRadius, arrowSize, anchor): """ Generate the QPainterPath used to draw the outline of the popup. Parameters ---------- rect : QRect Bounding rect for the popup. xRadius, yRadius : int x and y radius of the popup. arrowSize : QSize Width and height of the popup anchor arrow. anchor : int Positioning of the popup relative to the parent. Determines the position of the arrow. Returns ------- result : QPainterPath Path that can be passed to QPainter.drawPath to render popup. """ awidth, aheight = arrowSize.width(), arrowSize.height() draw_arrow = (awidth > 0 and aheight > 0) if anchor == QBubbleView.AnchorRight: rect.adjust(aheight, 0, 0, 0) elif anchor == QBubbleView.AnchorLeft: rect.adjust(0, 0, -aheight, 0) elif anchor == QBubbleView.AnchorBottom: rect.adjust(0, aheight, 0, 0) else: rect.adjust(0, 0, 0, -aheight) r = rect.normalized() if r.isNull(): return hw = r.width() / 2 hh = r.height() / 2 xRadius = 100 * min(xRadius, hw) / hw yRadius = 100 * min(yRadius, hh) / hh # The starting point of the path is the top left corner x = r.x() y = r.y() w = r.width() h = r.height() rxx2 = w * xRadius / 100 ryy2 = h * yRadius / 100 center = r.center() path = QPainterPath() path.arcMoveTo(x, y, rxx2, ryy2, 180) path.arcTo(x, y, rxx2, ryy2, 180, -90) if anchor == QBubbleView.AnchorBottom and draw_arrow: path.lineTo(center.x() - awidth, y) path.lineTo(center.x(), y - aheight) path.lineTo(center.x() + awidth, y) path.arcTo(x + w - rxx2, y, rxx2, ryy2, 90, -90) if anchor == QBubbleView.AnchorLeft and draw_arrow: path.lineTo(x + w, center.y() - awidth) path.lineTo(x + w + aheight, center.y()) path.lineTo(x + w, center.y() + awidth) path.arcTo(x + w - rxx2, y + h - ryy2, rxx2, ryy2, 0, -90) if anchor == QBubbleView.AnchorTop and draw_arrow: path.lineTo(center.x() + awidth, y + h) path.lineTo(center.x(), y + h + aheight) path.lineTo(center.x() - awidth, y + h) path.arcTo(x, y + h - ryy2, rxx2, ryy2, 270, -90) if anchor == QBubbleView.AnchorRight and draw_arrow: path.lineTo(x, center.y() + awidth) path.lineTo(x - aheight, center.y()) path.lineTo(x, center.y() - awidth) path.closeSubpath() return path
def _updatePP(self): """Create the neck geometry updating this item's QPainterPath. Return None. """ self.prepareGeometryChange() pp = QPainterPath() stringSpan = (self.nStrings - 1) * self.stringSpacing nutWidth = stringSpan + self.stringEdgeOffset * 2 # frets scaleLen = 25.5 offset = 0.0 # previous fret x coordinate self.fretXs = [0.0] for n in range(self.nFrets): pos = offset + (scaleLen - offset) / 17.817 self.fretXs.append(pos) pp.moveTo(pos, nutWidth) pp.lineTo(pos, 0.0) offset = pos # marker dots y = nutWidth / 2.0 for n in [3, 5, 7, 9, 12, 15, 17, 19, 21, 24]: if n > self.nFrets: break fretX1 = self.fretXs[n-1] fretX2 = self.fretXs[n] x = fretX1 + (fretX2 - fretX1) / 2.0 d = self.markerDia r = d / 2.0 dy = nutWidth / 4.0 if n % 12 == 0: pp.addEllipse(x-r, y-r-dy, d, d) pp.addEllipse(x-r, y-r+dy, d, d) else: pp.addEllipse(x-r, y-r, d, d) # strings self.stringYs = [] endX = self.fretXs[-1] for n in range(self.nStrings): y = self.stringEdgeOffset + self.stringSpacing * n self.stringYs.append(y) pp.moveTo(-self.nutThickness - self.fretXs[1] / 2.0, y) pp.lineTo(endX, y) # outline pp.addRect(0, 0, self.fretXs[-1], nutWidth) # nut pp.addRect(-self.nutThickness, 0, self.nutThickness, nutWidth) # partial headstock, to allow room for open note display # upper curve r = 2.0 d = self.fretXs[1] / 2.0 rectL = -self.nutThickness - r rect = QRectF(rectL, -r*2.0, r*2.0, r*2.0) ra = asin(d / r) da = degrees(ra) pp.arcMoveTo(rect, 270.0) pp.arcTo(rect, 270.0, -da) # lower curve rect = QRectF(rectL, nutWidth, r*2.0, r*2.0) pp.arcMoveTo(rect, 90.0) pp.arcTo(rect, 90.0, da) # x coordinate of open string note markers self.openX = (-self.nutThickness - sin(ra) * r) / 2.0 self.setPath(pp)