Пример #1
0
    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)
Пример #2
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
Пример #3
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
Пример #4
0
 def __init__(self, sug=None):
     super().__init__()
     p = QPen()
     p.setColor(QColor("red"))
     self.addLine(-5, 0, 5, 0, p)
     self.addLine(0, -5, 0, 5, p)
     self.sug = sug
     if self.sug:
         from grandalf.routing import route_with_lines
         self.sug.route_edge = route_with_lines
         self.sug.dx, self.sug.dy = 5, 5
         self.sug.dirvh = 0
         for n in self.sug.g.sV:
             self.connect_add(n.view)
         for e in self.sug.g.sE:
             e.view = Edge_basic(e.v[0].view.obj, e.v[1].view.obj)
             self.addItem(e.view)
Пример #5
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)