def draw_selection_rect(self, painter): cr, sr = self.target, self.selection_state.rect painter.setPen(self.SELECT_PEN) painter.setRenderHint(QPainter.RenderHint.Antialiasing, False) if self.selection_state.current_mode == 'selected': # Shade out areas outside the selection rect for r in ( QRectF(cr.topLeft(), QPointF(sr.left(), cr.bottom())), # left QRectF(QPointF(sr.left(), cr.top()), sr.topRight()), # top QRectF(QPointF(sr.right(), cr.top()), cr.bottomRight()), # right QRectF(sr.bottomLeft(), QPointF(sr.right(), cr.bottom())), # bottom ): painter.fillRect(r, self.SHADE_COLOR) dr = self.get_drag_rect() if self.selection_state.in_selection and dr is not None: # Draw the resize rectangle painter.save() painter.setCompositionMode( QPainter.CompositionMode.RasterOp_SourceAndNotDestination) painter.setClipRect(sr.adjusted(1, 1, -1, -1)) painter.drawRect(dr) painter.restore() # Draw the selection rectangle painter.setCompositionMode( QPainter.CompositionMode.RasterOp_SourceAndNotDestination) painter.drawRect(sr)
def draw_curved_line(painter_path, dx, dy, c1_frac, c1_amp, c2_frac, c2_amp): length = sqrt(dx * dx + dy * dy) angle = atan2(dy, dx) c1 = QPointF(*rotate_vector(angle, c1_frac * length, c1_amp * length)) c2 = QPointF(*rotate_vector(angle, c2_frac * length, c2_amp * length)) pos = painter_path.currentPosition() painter_path.cubicTo(pos + c1, pos + c2, pos + QPointF(dx, dy))
def _cell_polys(): poly = QPolygonF() l = 0.46/cos30 inner_poly = QPolygonF() il = 0.75*l for i in range(6): a = i*tau/6 - tau/12 poly.append(QPointF(l*math.sin(a), -l*math.cos(a))) inner_poly.append(QPointF(il*math.sin(a), -il*math.cos(a))) return poly, inner_poly
def draw(self, painter): for l in self.layouts: if hasattr(l, 'draw'): # Etch effect for the text painter.save() painter.setRenderHints(QPainter.RenderHint.TextAntialiasing | QPainter.RenderHint.Antialiasing) painter.save() painter.setPen(QColor(255, 255, 255, 125)) l.draw(painter, QPointF(1, 1)) painter.restore() l.draw(painter, QPointF()) painter.restore()
def _cell_polys(): # It will be 0.49*2+0.03 = 1.01 units high, so neighbors will slightly collide. poly = QPolygonF() l = 0.49 / cos30 # There is also a smaller inner part, for looks. inner_poly = QPolygonF() il = 0.77 * l for i in range(6): a = i * tau / 6 - tau / 12 poly.append(QPointF(l * math.sin(a), -l * math.cos(a))) inner_poly.append(QPointF(il * math.sin(a), -il * math.cos(a))) return poly, inner_poly
def __init__(self, scene): QGraphicsView.__init__(self, scene) self.scene = scene self.setBackgroundBrush(QBrush(qt.white)) self.setResizeAnchor(QGraphicsView.AnchorViewCenter) self.setTransformationAnchor(QGraphicsView.AnchorUnderMouse) self.setRenderHints(self.renderHints()|QPainter.Antialiasing) self.setHorizontalScrollBarPolicy(qt.ScrollBarAlwaysOff) self.setVerticalScrollBarPolicy(qt.ScrollBarAlwaysOff) inf = -1e10 self.setSceneRect(QRectF(QPointF(-inf, -inf), QPointF(inf, inf))) self.scale(50, 50) #*1.00955
def position(self, new_pos): (x, y) = new_pos self._position = Point(x, y) if self.layouts: self.layouts[0].setPosition(QPointF(x, y)) y += self.layouts[0].boundingRect().height() for l in self.layouts[1:]: if isinstance(l, numbers.Number): y += l else: l.setPosition(QPointF(x, y)) y += l.boundingRect().height()
def draw_fold(x, m=1, corner=left_corner): ans = p = QPainterPath(QPointF(x, rtop)) draw_curved_line(p, rwidth*m, 0, 0.1, 0.1*m, 0.5, -0.2*m) fold_upper = p.currentPosition() p.lineTo(p.currentPosition() + QPointF(-deltax*m, height)) fold_corner = p.currentPosition() draw_curved_line(p, -rwidth*m, 0, 0.2, -0.1*m, 0.8, -0.1*m) draw_curved_line(p, deltax*m, -height, 0.2, 0.1*m, 0.8, 0.1*m) p = inner_fold = QPainterPath(corner) dp = fold_corner - p.currentPosition() draw_curved_line(p, dp.x(), dp.y(), 0.5, 0.3*m, 1, 0*m) p.lineTo(fold_upper), p.closeSubpath() return ans, inner_fold
def __call__(self, painter, rect, color_theme, title_block, subtitle_block, footer_block): if not self.PATH_CACHE: from calibre.utils.speedups import svg_path_to_painter_path try: self.__class__.PATH_CACHE['corner'] = svg_path_to_painter_path( self.CORNER_VECTOR) except Exception: import traceback traceback.print_exc() p = painter painter.setRenderHint(QPainter.RenderHint.Antialiasing) g = QRadialGradient(QPointF(rect.center()), rect.width()) g.setColorAt(0, self.color1), g.setColorAt(1, self.color2) painter.fillRect(rect, QBrush(g)) painter.save() painter.setWindow(0, 0, *self.VIEWPORT) try: path = self.PATH_CACHE['corner'] except KeyError: path = QPainterPath() pen = p.pen() pen.setColor(self.ccolor1) p.setPen(pen) def corner(): b = QBrush(self.ccolor1) p.fillPath(path, b) p.rotate(90), p.translate(100, -100), p.scale(1, -1), p.translate( -103, -97) p.fillPath(path, b) p.setWorldTransform(QTransform()) # Top-left corner corner() # Top right corner p.scale(-1, 1), p.translate(-400, 0), corner() # Bottom left corner p.scale(1, -1), p.translate(0, -500), corner() # Bottom right corner p.scale(-1, -1), p.translate(-400, -500), corner() for y in (28.4, 471.7): p.drawLine(QPointF(160, y), QPointF(240, y)) for x in (31.3, 368.7): p.drawLine(QPointF(x, 155), QPointF(x, 345)) pen.setWidthF(1.8) p.setPen(pen) for y in (23.8, 476.7): p.drawLine(QPointF(160, y), QPointF(240, y)) for x in (26.3, 373.7): p.drawLine(QPointF(x, 155), QPointF(x, 345)) painter.restore() return self.ccolor2, self.ccolor2, self.ccolor1
def fit_inside(parent, item, k): "Fit one QGraphicsItem inside another, scale by height and center it" sb = parent.boundingRect() tb = item.boundingRect() item.setScale(sb.height()/tb.height()*k) tb = item.mapRectToItem(parent, item.boundingRect()) item.setPos(sb.center() - QPointF(tb.size().width()/2, tb.size().height()/2))
def hex1(): result = QPolygonF() l = 0.5/cos30 for i in range(6): a = i*tau/6 - tau/12 result.append(QPointF(l*math.sin(a), -l*math.cos(a))) return result
def flower_neighbors(self): if not self.scene(): return for dx, dy in [ # order: (clockwise, closest) starting from north (0, -1), (0, -2), (1, -1.5), (1, -0.5), (2, -1), (2, 0), (1, 0.5), (2, 1), (1, 1.5), (0, 1), (0, 2), (-1, 1.5), (-1, 0.5), (-2, 1), (-2, 0), (-1, -0.5), (-2, -1), (-1, -1.5), ]: dx *= cos30 pos = self.scenePos() + QPointF(dx, dy) it = self.scene().itemAt(pos, QTransform()) if not it: continue if distance(pos, it.scenePos()) < 1e-2: yield it
def __init__(self, text='', width=0, font=None, img=None, max_height=100, align=Qt.AlignmentFlag.AlignCenter): self.layouts = [] self._position = Point(0, 0) self.leading = self.line_spacing = 0 if font is not None: fm = QFontMetrics(font, img) self.leading = fm.leading() self.line_spacing = fm.lineSpacing() for text in text.split('<br>') if text else (): text, formats = parse_text_formatting(sanitize(text)) l = QTextLayout(unescape_formatting(text), font, img) l.setAdditionalFormats(formats) to = QTextOption(align) to.setWrapMode(QTextOption.WrapMode.WrapAtWordBoundaryOrAnywhere) l.setTextOption(to) l.beginLayout() height = 0 while height + 3*self.leading < max_height: line = l.createLine() if not line.isValid(): break line.setLineWidth(width) height += self.leading line.setPosition(QPointF(0, height)) height += line.height() max_height -= height l.endLayout() if self.layouts: self.layouts.append(self.leading) else: self._position = Point(l.position().x(), l.position().y()) self.layouts.append(l) if self.layouts: self.layouts.append(self.leading)
def __init__(self, gui): QWidget.__init__(self, gui) self.setObjectName('jobs_pointer') self.setVisible(False) self.resize(100, 80) self.animation = QPropertyAnimation(self, b"geometry", self) self.animation.setDuration(750) self.animation.setLoopCount(2) self.animation.setEasingCurve(QEasingCurve.Type.Linear) self.animation.finished.connect(self.hide) taily, heady = 0, 55 self.arrow_path = QPainterPath(QPointF(40, taily)) self.arrow_path.lineTo(40, heady) self.arrow_path.lineTo(20, heady) self.arrow_path.lineTo(50, self.height()) self.arrow_path.lineTo(80, heady) self.arrow_path.lineTo(60, heady) self.arrow_path.lineTo(60, taily) self.arrow_path.closeSubpath() c = self.palette().color(QPalette.ColorGroup.Active, QPalette.ColorRole.WindowText) self.color = QColor(c) self.color.setAlpha(100) self.brush = QBrush(self.color, Qt.BrushStyle.SolidPattern)
def __call__(self, painter, rect, color_theme, title_block, subtitle_block, footer_block): painter.fillRect(rect, self.color1) top = title_block.position.y + 2 extra_spacing = subtitle_block.line_spacing // 2 if subtitle_block.line_spacing else title_block.line_spacing // 3 height = title_block.height + subtitle_block.height + extra_spacing + title_block.leading right = rect.right() - self.hmargin width = right - self.hmargin # Draw main banner p = main = QPainterPath(QPointF(self.hmargin, top)) draw_curved_line(p, rect.width() - 2 * self.hmargin, 0, 0.1, -0.1, 0.9, -0.1) deltax = self.GRADE * height p.lineTo(right + deltax, top + height) right_corner = p.currentPosition() draw_curved_line(p, - width - 2 * deltax, 0, 0.1, 0.05, 0.9, 0.05) left_corner = p.currentPosition() p.closeSubpath() # Draw fold rectangles rwidth = self.fold_width yfrac = 0.1 width23 = int(0.67 * rwidth) rtop = top + height * yfrac def draw_fold(x, m=1, corner=left_corner): ans = p = QPainterPath(QPointF(x, rtop)) draw_curved_line(p, rwidth*m, 0, 0.1, 0.1*m, 0.5, -0.2*m) fold_upper = p.currentPosition() p.lineTo(p.currentPosition() + QPointF(-deltax*m, height)) fold_corner = p.currentPosition() draw_curved_line(p, -rwidth*m, 0, 0.2, -0.1*m, 0.8, -0.1*m) draw_curved_line(p, deltax*m, -height, 0.2, 0.1*m, 0.8, 0.1*m) p = inner_fold = QPainterPath(corner) dp = fold_corner - p.currentPosition() draw_curved_line(p, dp.x(), dp.y(), 0.5, 0.3*m, 1, 0*m) p.lineTo(fold_upper), p.closeSubpath() return ans, inner_fold left_fold, left_inner = draw_fold(self.hmargin - width23) right_fold, right_inner = draw_fold(right + width23, m=-1, corner=right_corner) painter.save() painter.setRenderHint(QPainter.RenderHint.Antialiasing) pen = QPen(self.ccolor2) pen.setWidth(3) pen.setJoinStyle(Qt.PenJoinStyle.RoundJoin) painter.setPen(pen) for r in (left_fold, right_fold): painter.fillPath(r, QBrush(self.color2)) painter.drawPath(r) for r in (left_inner, right_inner): painter.fillPath(r, QBrush(self.color2.darker())) painter.drawPath(r) painter.fillPath(main, QBrush(self.color2)) painter.drawPath(main) painter.restore() return self.ccolor2, self.ccolor2, self.ccolor1
def paintEvent(self, ev): if self.last_layout_rect != self.rect(): self.do_layout() p = QPainter(self) br = self.layout.boundingRect() y = 0 if br.height() < self.height(): y = (self.height() - br.height()) / 2 self.layout.draw(p, QPointF(0, y))
def __init__(self): self.fill = QBrush(Qt.GlobalColor.white) self.stroke = QPen() self.opacity = 1.0 self.transform = QTransform() self.brush_origin = QPointF() self.clip_updated = False self.do_fill = False self.do_stroke = True self.qt_pattern_cache = {}
def copy(self): ans = GraphicsState() ans.fill = QBrush(self.fill) ans.stroke = QPen(self.stroke) ans.opacity = self.opacity ans.transform = self.transform * QTransform() ans.brush_origin = QPointF(self.brush_origin) ans.clip_updated = self.clip_updated ans.do_fill, ans.do_stroke = self.do_fill, self.do_stroke return ans
def upd(self, first=False): self.reset_cache() if self.display is Cell.unknown: self.setBrush(Color.yellow_border) self._inner.setBrush(Color.yellow) self._text.setText('') elif self.display is Cell.empty: self.setBrush(Color.black_border) self._inner.setBrush(Color.black) elif self.display is Cell.full: self.setBrush(Color.blue_border) self._inner.setBrush(Color.blue) if not self.placed: return if self.display is not Cell.unknown and self.value is not None: txt = str(self.value) if self.together is not None: txt = ('{{{}}}' if self.together else '-{}-').format(txt) else: txt = '?' if self.display is Cell.empty else '' self._text.setText(txt) if txt: fit_inside(self, self._text, 0.48) if self.extra_text: unknown = self.display is Cell.unknown fit_inside(self, self._extra_text, 0.31) self._extra_text.setPos(self._extra_text.pos() + QPointF(0, -0.2)) self._extra_text.setBrush(Color.dark_text if unknown else Color.light_text) if txt and self.extra_text: self._text.setPos(self._text.pos() + QPointF(0, 0.1)) self.update() if first: with self.upd_neighbors(): pass
def flower_neighbors(self): if not self.scene(): return poly = QPolygonF() l = 1.7 for i in range(6): a = i*tau/6 poly.append(QPointF(self.x()+l*math.sin(a), self.y()+l*math.cos(a))) for it in self.scene().items(poly): if isinstance(it, Cell) and it is not self: yield it
def __init__(self): # The collision box is rectangular poly = QPolygonF() poly.append(QPointF(-0.25, 0.48)) poly.append(QPointF(-0.25, 0.02)) poly.append(QPointF(0.25, 0.02)) poly.append(QPointF(0.25, 0.48)) #l = 0.49/cos30 #for i in range(6): #a = i*tau/6-tau/12 #poly.append(QPointF(l*math.sin(a), -l*math.cos(a))) QGraphicsPolygonItem.__init__(self, poly) self.setBrush(QColor(255, 255, 255, 0)) #self.setPen(QPen(qt.red, 0)) self.setPen(no_pen) self._text = QGraphicsSimpleTextItem('v') self._text.setBrush(Color.dark_text) fit_inside(self, self._text, 0.8)
def move_selection_rect(self, x, y): sr = self.selection_state.rect half_width = sr.width() / 2.0 half_height = sr.height() / 2.0 c = sr.center() nx = c.x() + x ny = c.y() + y minx = self.target.left() + half_width maxx = self.target.right() - half_width miny, maxy = self.target.top() + half_height, self.target.bottom() - half_height nx = max(minx, min(maxx, nx)) ny = max(miny, min(maxy, ny)) sr.moveCenter(QPointF(nx, ny))
def do_layout(self): ly = self.layout ly.beginLayout() w = self.width() - 5 height = 0 leading = self.fontMetrics().leading() while True: line = ly.createLine() if not line.isValid(): break line.setLineWidth(w) height += leading line.setPosition(QPointF(5, height)) height += line.height() ly.endLayout()
def start(self): if config['disable_animations']: return self.setVisible(True) self.raise_() end = self.abspos(self.gui.jobs_button) end = QPointF(end.x() + self.gui.jobs_button.width()/3.0, end.y()+20) start = QPointF(end.x(), end.y() - 0.5*self.height()) self.path = QPainterPath(QPointF(start)) self.path.lineTo(end) self.path.closeSubpath() self.animation.setStartValue(self.rect_at(0.0)) self.animation.setEndValue(self.rect_at(1.0)) self.animation.setDirection(QAbstractAnimation.Direction.Backward) num_keys = 100 for i in range(1, num_keys): i /= num_keys self.animation.setKeyValueAt(i, self.rect_at(i)) self.animation.start()
def update(self, tp): self.current_position = tp.pos() now = monotonic() self.time_since_last_update = now - self.last_update_time self.last_update_time = now self.previous_screen_position, self.current_screen_position = self.current_screen_position, QPointF( tp.screenPos()) movement = (self.current_screen_position - self.previous_screen_position).manhattanLength() self.total_movement += movement if movement > 5: self.time_of_last_move = now
def __init__(self, tp): self.creation_time = self.last_update_time = self.time_of_last_move = monotonic( ) self.start_screen_position = self.current_screen_position = self.previous_screen_position = QPointF( tp.screenPos()) self.time_since_last_update = -1 self.total_movement = 0 self.start_position = self.current_position = tp.pos() self.extra_data = None
def spread_gradient(self, gradient, pixel_page_width, pixel_page_height, matrix): start = gradient.start() stop = gradient.finalStop() stops = list(map(lambda x: [x[0], x[1].getRgbF()], gradient.stops())) spread = gradient.spread() if spread != gradient.PadSpread: inv = matrix.inverted()[0] page_rect = tuple( map(inv.map, (QPointF(0, 0), QPointF( pixel_page_width, 0), QPointF(0, pixel_page_height), QPointF(pixel_page_width, pixel_page_height)))) maxx = maxy = -sys.maxsize - 1 minx = miny = sys.maxsize for p in page_rect: minx, maxx = min(minx, p.x()), max(maxx, p.x()) miny, maxy = min(miny, p.y()), max(maxy, p.y()) def in_page(point): return (minx <= point.x() <= maxx and miny <= point.y() <= maxy) offset = stop - start llimit, rlimit = start, stop reflect = False base_stops = copy.deepcopy(stops) reversed_stops = list(reversed(stops)) do_reflect = spread == gradient.ReflectSpread totl = abs(stops[-1][0] - stops[0][0]) intervals = [ abs(stops[i + 1][0] - stops[i][0]) / totl for i in range(len(stops) - 1) ] while in_page(llimit): reflect ^= True llimit -= offset estops = reversed_stops if (reflect and do_reflect) else base_stops stops = copy.deepcopy(estops) + stops first_is_reflected = reflect reflect = False while in_page(rlimit): reflect ^= True rlimit += offset estops = reversed_stops if (reflect and do_reflect) else base_stops stops = stops + copy.deepcopy(estops) start, stop = llimit, rlimit num = len(stops) // len(base_stops) if num > 1: # Adjust the stop parameter values t = base_stops[0][0] rlen = totl / num reflect = first_is_reflected ^ True intervals = [i * rlen for i in intervals] rintervals = list(reversed(intervals)) for i in range(num): reflect ^= True pos = i * len(base_stops) tvals = [t] for ival in (rintervals if reflect and do_reflect else intervals): tvals.append(tvals[-1] + ival) for j in range(len(base_stops)): stops[pos + j][0] = tvals[j] t = tvals[-1] # In case there were rounding errors stops[-1][0] = base_stops[-1][0] return start, stop, tuple(Stop(s[0], s[1]) for s in stops)
if self.display!=self.kind: r.append('({})'.format(repr(self.kind).split('.')[1])) r.append(self._text.text()) try: r.append('#{}'.format(self.id)) except AttributeError: pass if first: r.append('neighbors:[{}]'.format(' '.join(m.__repr__(False) for m in self.neighbors))) if self.members: r.append('members:[{}]'.format(' '.join(m.__repr__(False) for m in self.members))) return '<{}>'.format(' '.join(str(p) for p in r if str(p))) _col_poly = QPolygonF() for x, y in [(-0.25, 0.48), (-0.25, 0.02), (0.25, 0.02), (0.25, 0.48)]: _col_poly.append(QPointF(x, y)) _col_angle_deltas = {-60: (1, 1), 0: (0, 1), 60: (-1, 1)} class Column(QGraphicsPolygonItem, Item): "Column number marker" def __init__(self): QGraphicsPolygonItem.__init__(self, _col_poly) self.show_info = False self.setBrush(QColor(255, 255, 255, 0)) self.setPen(no_pen) self._text = QGraphicsSimpleTextItem('v') self._text.setBrush(Color.dark_text)
def __call__(self, painter, rect, color_theme, title_block, subtitle_block, footer_block): g = QLinearGradient(QPointF(0, 0), QPointF(0, rect.height())) g.setStops([(0, self.color1), (0.7, self.color2), (1, self.color1)]) painter.fillRect(rect, QBrush(g)) return self.ccolor1, self.ccolor1, self.ccolor1