def paintEvent(self, event):
        painter = QPainter(self)
        painter.setRenderHint(QPainter.Antialiasing)

        center = QPointF(self.width() / 2, self.height() / 2)
        radius = self.radius()
        ellipse_line_width = self.radius() * 60 / 512

        # big ellipse
        pen = QPen()
        pen.setWidth(ellipse_line_width)
        pen.setColor(self.color)
        painter.setPen(pen)
        painter.drawEllipse(center, radius - pen.width() / 2,
                            radius - pen.width() / 2)

        # dots
        pen = QPen()
        pen.setColor(QColor(0, 0, 0, 0))
        painter.setPen(pen)
        brush = QBrush()
        brush.setStyle(Qt.SolidPattern)
        dot_size = radius * 200 / 1024
        color = copy.copy(self.color)

        self._change_color(painter, brush, color, 0)
        painter.drawEllipse(
            QPointF((self.width() - radius - ellipse_line_width / 2) / 2,
                    self.height() / 2), dot_size, dot_size)
        self._change_color(painter, brush, color, 15)
        painter.drawEllipse(center, dot_size, dot_size)
        self._change_color(painter, brush, color, 30)
        painter.drawEllipse(
            QPointF((self.width() + radius + ellipse_line_width / 2) / 2,
                    self.height() / 2), dot_size, dot_size)
Exemple #2
0
 def draw_cursor(self, event_x, event_y, drawing_tool_radius,
                 new_circle=False):
     """
     Draws a blue circle where the user clicked. :param event_x:
     QGraphicsScene event attribute: event.scenePos().x() :param event_y:
     QGraphicsScene event attribute: event.scenePos().y() :param
     drawing_tool_radius: the current radius of the drawing tool :param
     new_circle: True when the circle object is being created rather than
     updated.
     """
     self.draw_tool_radius = drawing_tool_radius
     self.current_cursor_x = event_x - self.draw_tool_radius
     self.current_cursor_y = event_y - self.draw_tool_radius
     if new_circle:
         self.cursor = QGraphicsEllipseItem(self.current_cursor_x,
                                            self.current_cursor_y,
                                            self.draw_tool_radius * 2,
                                            self.draw_tool_radius * 2)
         pen = QPen(QColor("blue"))
         pen.setWidth(0)
         self.cursor.setPen(pen)
         self.cursor.setZValue(1)
         self.addItem(self.cursor)
     elif self.cursor is not None:
         self.cursor.setRect(self.current_cursor_x, self.current_cursor_y,
                             self.draw_tool_radius * 2,
                             self.draw_tool_radius * 2)
Exemple #3
0
 def particle_pen(self, index: int):
     pen = QPen()
     colors = self.settings.list_value(default_settings.particle_color)
     colors = [QColor(c) for c in colors]
     pen.setColor(colors[index % len(colors)])
     pen.setStyle(Qt.SolidLine)
     pen.setWidth(0)
     return pen
Exemple #4
0
 def create_icon(player_colour: QColor) -> QPixmap:
     size = 200
     icon = QPixmap(size, size)
     icon.fill(Qt.transparent)
     painter = QPainter(icon)
     try:
         painter.setBrush(player_colour)
         pen = QPen()
         pen.setWidth(3)
         painter.setPen(pen)
         painter.drawEllipse(1, 1, size - 2, size - 2)
     finally:
         painter.end()
     return icon
Exemple #5
0
 def resizeEvent(self, event):
     bounds = self.scene.itemsBoundingRect()
     if bounds.width() <= 0 or bounds.height() <= 0:
         return  # do nothing if size is zero
     self.view.fitInView(bounds, Qt.KeepAspectRatio)
     if self.rectangle is not None:
         self.scene.removeItem(self.rectangle)
     pen = QPen(Qt.green)
     pen.setWidth(0)
     pen.setStyle(Qt.DashLine)
     self.rectangle = self.scene.addRect(
         self.calculate_center_square(bounds), pen)
     self.view.centerOn(0, 0)
     self.view.raise_()
Exemple #6
0
 def trajectory_pen(self, index: int):
     if self.settings.boolean_value(
             default_settings.same_trajectory_color_with_particle):
         return self.particle_pen(index)
     else:
         pen = QPen()
         colors = self.settings.list_value(
             default_settings.trajectory_color)
         colors = [QColor(c) for c in colors]
         pen.setStyle(Qt.SolidLine)
         pen.setColor(colors[index % len(colors)])
         pen.setWidth(
             self.settings.int_value(default_settings.trajectory_size))
         pen.setJoinStyle(Qt.RoundJoin)
         pen.setCapStyle(Qt.RoundCap)
         return pen
Exemple #7
0
 def paint(self, painter, option, widget=None):
     qgp = self.getqgp()
     pen = QPen()
     pen.setWidth(2)
     qgp.setPen(pen)
     qgp.setBrush(QBrush(Qt.NoBrush))
     painter.setClipRect(option.exposedRect)
     qgp.paint(painter, option, widget)
     lastp = self.points[-1]
     angle = radians(qgp.path().angleAtPercent(1.0))
     angle = angle + pi
     p = lastp + QPointF(
         cos(angle - pi / 6.0) * 10, -sin(angle - pi / 6.0) * 10)
     q = lastp + QPointF(
         cos(angle + pi / 6.0) * 10, -sin(angle + pi / 6.0) * 10)
     painter.setBrush(QBrush(QColor("black")))
     self.head = QPolygonF([lastp, p, q])
     painter.drawPolygon(self.head)
Exemple #8
0
 def paintmap(self, surface):
     ww = surface.window().width()
     wh = surface.window().height()
     self.vb.setMaximum(self.qimg.height() - (wh // self.line.height))
     self.line.x_map = ww - 32
     r = QRect(self.line.x_map, 2, 32, wh - 4)
     surface.drawImage(r, self.qimg)
     factor = wh / self.qimg.height()
     pen = surface.pen()
     p = QPen(Qt.white)
     p.setCapStyle(Qt.RoundCap)
     p.setWidth(2)
     surface.setPen(p)
     l0 = self.vb.value() * factor
     l1 = l0 + (wh // self.line.height) * factor
     pad = 4
     p1 = QPointF(self.line.x_map - pad, l0)
     p2 = QPointF(self.line.x_map - pad, l1)
     if l1 - l0 > 4:
         p.setWidth(2)
         surface.drawLine(p1, p2)
         surface.drawLine(p1, QPointF(self.line.x_map, l0))
         surface.drawLine(p2, QPointF(self.line.x_map, l1))
     else:
         p.setWidth(4)
         surface.drawLine(p1, p2)
     surface.setPen(pen)
Exemple #9
0
 def draw(self, painter: QPainter):
     render_display(self.display, painter)
     pen = QPen()
     pen.setWidth(self.width // 50)
     pen.setCapStyle(Qt.PenCapStyle.RoundCap)
     painter.setPen(pen)
Exemple #10
0
    def draw(self, art: QPixmap, painter: typing.Optional[QPainter] = None):
        filled_portion = 0.6 if self.is_shuffled and not self.row_clues else 0.9
        scaled_art = art.scaled(self.rect.width() * filled_portion,
                                self.rect.height() * filled_portion,
                                Qt.AspectRatioMode.KeepAspectRatio)
        if painter is None:
            painter = QPainter(self.target)
        painter.fillRect(self.rect, QColor('white'))
        cell_height = round(scaled_art.height() / self.rows)
        vertical_padding = self.rect.height() - self.rows * cell_height
        row_padding = vertical_padding / self.rows
        cell_width = round(scaled_art.width() / self.cols)
        horizontal_padding = self.rect.width() - self.cols * cell_width
        col_padding = horizontal_padding / self.cols
        padding = min(row_padding, col_padding)
        left_border = self.cols * (col_padding - padding) / 2
        top_border = self.rows * (row_padding - padding) / 2
        font = painter.font()
        font.setPixelSize(padding / 2.6)
        painter.setFont(font)
        old_pen = painter.pen()
        grey_pen = QPen(QColor('lightgrey'))
        width = max(cell_width / 35, 2)
        grey_pen.setWidth(round(width))
        y = top_border
        cell_index = 0
        for i in range(self.rows):
            x = left_border
            for j in range(self.cols):
                si, sj, label = self.cells[cell_index]
                clue = self.clues.get(label.lower(), label)
                sx = sj * cell_width
                sy = si * cell_height
                painter.setPen(grey_pen)
                painter.drawRect(x + padding / 2, y, cell_width, cell_height)
                painter.setPen(old_pen)
                if self.is_shuffled:
                    original_size = new_size = font.pixelSize()
                    while True:
                        # noinspection PyTypeChecker
                        rect = painter.boundingRect(0, 0, cell_width, padding,
                                                    Qt.AlignmentFlag.AlignLeft,
                                                    clue)
                        if (rect.width() <= cell_width + padding
                                and rect.height() <= padding):
                            break
                        new_size *= 0.9
                        font.setPixelSize(new_size)
                        painter.setFont(font)
                    if not self.row_clues:
                        painter.drawText(x, y + cell_height,
                                         cell_width + padding, padding,
                                         Qt.AlignmentFlag.AlignHCenter, clue)
                    else:
                        painter.drawPixmap(x + padding / 2, y, cell_width,
                                           cell_height, self.row_clues[si], 0,
                                           0, 0, 0)
                        painter.drawPixmap(x + padding / 2, y, cell_width,
                                           cell_height, self.column_clues[sj],
                                           0, 0, 0, 0)
                    font.setPixelSize(original_size)
                    painter.setFont(font)
                painter.drawPixmap(x + padding / 2, y, cell_width, cell_height,
                                   scaled_art, sx, sy, cell_width, cell_height)

                x += cell_width + padding
                cell_index += 1

            y += cell_height + padding
Exemple #11
0
class HexAreaWidget(QWidget):
    '''
    Responsible for painting the area that actually containts the hex display
    '''

    signal_resized = Signal()
    signal_scroll_wheel_changed = Signal(int)
    signal_cursor_changed = Signal(int)
    signal_selection_updated = Signal(int)
    signal_key_cursor_pressed = Signal(KeyType)
    signal_key_selection_pressed = Signal(KeyType)
    signal_context_menu_shown = Signal(QPoint)
    signal_show_tooltip_at_offset = Signal(int, QPoint)
    signal_go_to_pointer_at_offset = Signal(int)

    def __init__(self, parent: QWidget):
        # , scroll_bar: QScrollBar, statusBar: QLabel
        super().__init__(parent=parent)

        self.line_height = 18
        self.byte_width = 25
        self.bytes_per_line = settings.get_bytes_per_line()

        self.label_offset_x = 5
        self.label_length = 100
        self.is_dragging_to_select = False

        self.display_data: List[DisplayByte] = []
        self.display_labels: List[str] = []

        # TODO make configurable
        self.font = QFont('DejaVu Sans Mono, Courier, Monospace', 12)
        self.label_color = QColor(128, 128, 128)
        self.byte_color = QColor(210, 210, 210)
        self.selection_color = QPen(QColor(97, 175, 239))
        self.selection_color.setWidth(2)
        self.annotation_pen = QPen(QColor(0, 0, 0), 2)
        self.enabled_constraint_pen = QPen(QColor(255, 80, 0), 2)
        self.disabled_constraint_pen = QPen(QColor(130, 40, 0), 2)

        # Make this widget focussable on click, so that we can reduce the context of the shortcut, so that multiple shortcuts are possible in the same window
        self.setFocusPolicy(Qt.FocusPolicy.ClickFocus)

    def wheelEvent(self, event):
        # TODO make scroll speed configurable
        lines_delta = -int(
            event.angleDelta().y() / self.line_height) * self.bytes_per_line

        self.signal_scroll_wheel_changed.emit(lines_delta)

    def resizeEvent(self, event: QResizeEvent) -> None:
        self.signal_resized.emit()

    def paintEvent(self, ev):
        p = QPainter(self)
        p.setFont(self.font)
        #p.fillRect(self.rect(), QBrush(Qt.blue))

        length = len(self.display_data)

        # Reduce to the number of lines that are available in the data
        num_rows = length // self.bytes_per_line
        if length % self.bytes_per_line > 0:
            num_rows += 1

        for l in range(num_rows):
            p.setPen(self.label_color)
            # Draw address label
            # self.instance.get_local_label(self.start_offset + l * self.bytes_per_line)
            position_string = self.display_labels[l]
            p.drawText(QPoint(self.label_offset_x, (l + 1) * self.line_height),
                       position_string)

            for i in range(
                    0,
                    min(self.bytes_per_line,
                        length - self.bytes_per_line * l)):

                #virtual_address = self.start_offset + l*self.bytes_per_line + i

                p.setPen(self.byte_color)

                current_byte = self.display_data[i + l * self.bytes_per_line]
                if current_byte.background is not None:
                    p.setBackground(current_byte.background)
                    p.setBackgroundMode(Qt.OpaqueMode)

                p.drawText(
                    QPoint(self.label_length + i * self.byte_width,
                           (l + 1) * self.line_height), current_byte.text)
                p.setBackgroundMode(Qt.TransparentMode)

                # Draw selection rects
                if current_byte.is_selected:
                    p.setPen(self.selection_color)
                    p.drawRect(
                        # TODO make these offsets configurable/dependent on font?
                        self.label_length + i * self.byte_width - 3,
                        (l) * self.line_height + 3,
                        self.byte_width,
                        self.line_height)

                # Draw annotation underlines
                if len(current_byte.annotations) > 0:
                    y_offset = 0
                    for annotation in current_byte.annotations:
                        self.annotation_pen.setColor(annotation.color)
                        p.setPen(self.annotation_pen)
                        x = self.label_length + i * self.byte_width
                        y = (l + 1) * self.line_height + y_offset + 2
                        p.drawLine(x, y, x + self.byte_width, y)
                        y_offset += 2

                # Draw constraint pipes
                if len(current_byte.constraints) > 0:
                    enabled = False
                    for constraint in current_byte.constraints:
                        if constraint.enabled:
                            enabled = True
                            break
                    if enabled:
                        p.setPen(self.enabled_constraint_pen)
                    else:
                        p.setPen(self.disabled_constraint_pen)
                    x = self.label_length + i * self.byte_width - 2
                    y = (l) * self.line_height + 3
                    p.drawLine(x, y, x, y + self.line_height)

    def number_of_lines_on_screen(self):
        # +1 to draw cutof lines as well
        return int(self.height() // self.line_height) + 1

    def contextMenuEvent(self, event: QContextMenuEvent) -> None:
        self.signal_context_menu_shown.emit(event.globalPos())

    def mousePressEvent(self, event: QMouseEvent) -> None:
        if event.button() == Qt.LeftButton:

            # TODO handle click on label, etc
            offset = self.xy_to_offset(event.x(), event.y())
            if offset is not None:

                ctrl = event.modifiers(
                ) & Qt.ControlModifier == Qt.ControlModifier
                shift = event.modifiers(
                ) & Qt.ShiftModifier == Qt.ShiftModifier

                if ctrl:
                    # Go to pointer
                    self.signal_go_to_pointer_at_offset.emit(offset)
                    return

                if shift:
                    # Move selection instead of cursor
                    self.signal_selection_updated.emit(offset)
                    self.is_dragging_to_select = True
                    return
                self.signal_cursor_changed.emit(offset)
                self.is_dragging_to_select = True

    def mouseMoveEvent(self, event: QMouseEvent) -> None:
        if self.is_dragging_to_select:
            offset = self.xy_to_offset(event.x(), event.y())
            if offset is not None:
                self.signal_selection_updated.emit(offset)

    def mouseReleaseEvent(self, event: QMouseEvent) -> None:
        self.is_dragging_to_select = False

    def xy_to_offset(self, x, y) -> Optional[int]:
        '''
        Returns offsets in bytes from the start_offset or None if not clicked on a byte
        '''
        line = y // self.line_height
        start = self.label_offset_x + self.label_length
        if x < start or x > start + self.bytes_per_line * self.byte_width:
            return None
        col = (x - start) // (self.byte_width)
        return line * self.bytes_per_line + col

    def keyPressEvent(self, event: QKeyEvent) -> None:
        shift = event.modifiers() & Qt.ShiftModifier == Qt.ShiftModifier
        key = event.key()
        if key == Qt.Key_Up:
            if shift:
                self.signal_key_selection_pressed.emit(KeyType.UP)
            else:
                self.signal_key_cursor_pressed.emit(KeyType.UP)
        elif key == Qt.Key_Down:
            if shift:
                self.signal_key_selection_pressed.emit(KeyType.DOWN)
            else:
                self.signal_key_cursor_pressed.emit(KeyType.DOWN)
        elif key == Qt.Key_Left:
            if shift:
                self.signal_key_selection_pressed.emit(KeyType.LEFT)
            else:
                self.signal_key_cursor_pressed.emit(KeyType.LEFT)
        elif key == Qt.Key_Right:
            if shift:
                self.signal_key_selection_pressed.emit(KeyType.RIGHT)
            else:
                self.signal_key_cursor_pressed.emit(KeyType.RIGHT)
        elif key == Qt.Key_PageUp:
            if shift:
                self.signal_key_selection_pressed.emit(KeyType.PAGE_UP)
            else:
                self.signal_key_cursor_pressed.emit(KeyType.PAGE_UP)
        elif key == Qt.Key_PageDown:
            if shift:
                self.signal_key_selection_pressed.emit(KeyType.PAGE_DOWN)
            else:
                self.signal_key_cursor_pressed.emit(KeyType.PAGE_DOWN)
        elif key == Qt.Key_Home:
            if shift:
                self.signal_key_selection_pressed.emit(KeyType.HOME)
            else:
                self.signal_key_cursor_pressed.emit(KeyType.HOME)
        elif key == Qt.Key_End:
            if shift:
                self.signal_key_selection_pressed.emit(KeyType.END)
            else:
                self.signal_key_cursor_pressed.emit(KeyType.END)

    def event(self, event: QEvent) -> bool:
        if event.type() == QEvent.ToolTip:
            offset = self.xy_to_offset(event.pos().x(), event.pos().y())
            if offset is None:
                QToolTip.hideText()
                return True
            self.signal_show_tooltip_at_offset.emit(offset, event.globalPos())
            return True

        return super().event(event)