diff --git a/src/simudator/gui/signal_viewer.py b/src/simudator/gui/signal_viewer.py index 3c00b00b02288c97290000898fa8b924a6a58cc5..3f57eff836a5fb7a0235e4bfb0fd34775051ecbc 100644 --- a/src/simudator/gui/signal_viewer.py +++ b/src/simudator/gui/signal_viewer.py @@ -1,7 +1,5 @@ -from qtpy.QtCore import QPointF, QRectF, Qt -from qtpy.QtCore import Signal as pyqtSignal -from qtpy.QtCore import Slot -from qtpy.QtGui import QPainter, QPainterPath, QPainterPathStroker, QPalette, QPen +from qtpy.QtCore import Property, QPointF, QRectF, Qt, Slot +from qtpy.QtGui import QBrush, QColor, QFont, QPainter, QPainterPath, QPen from qtpy.QtWidgets import ( QGraphicsItem, QGraphicsWidget, @@ -26,11 +24,16 @@ class SignalViewer(QGraphicsWidget): super().__init__(parent, flags) self._signal = signal self._label = label - self._width: int = SignalViewer.DEFAULT_WIDTH - self._height: int = SignalViewer.DEFAULT_HEIGHT - self.outline_width: float = 1 self.setFlag(QGraphicsItem.ItemIsMovable) - self.setFiltersChildEvents(False) + self.resize(self.DEFAULT_WIDTH, self.DEFAULT_HEIGHT) + + # Default values for properties for appearance + # TODO: Put these values in constants? + self._outline_width = 1 + self._outline = self.palette().windowText() + self._background = self.palette().window() + self._text_color = self.palette().windowText().color() + self._text_font = QFont("Sans Serif", 9) def paint( self, @@ -40,45 +43,93 @@ class SignalViewer(QGraphicsWidget): ) -> None: painter.save() - # Draw outline of the items shape with fill - palette: QPalette = option.palette - pen = QPen(palette.color(QPalette.ColorRole.Dark)) - brush = palette.brush(QPalette.ColorRole.Base) + width = self.size().width() + height = self.size().height() + + # Draw the base shape of the signal viewer + pen = QPen(self.outline, self.outline_width) painter.setPen(pen) - painter.setBrush(brush) + painter.setBrush(self.background) painter.drawPath(self.shape()) + # Set text specific painter settings + painter.setPen(QPen(self.text_color)) + painter.setBrush(QBrush(self.text_color)) + painter.setFont(self.text_font) + # Draw label if any - value_height_offset = self._height / 2 + value_y_start = 0 if self._label is not None: - # TODO: Proper positioning on the y-axis - x_pos = self._width / 2 - len(self._label) * 3 - text_pos = QPointF(x_pos, self._height / 3) - painter.setPen(palette.text().color()) - painter.setBrush(palette.text()) - painter.drawText(text_pos, self._label) - value_height_offset = self._height * 2 / 3 + text_rect = QRectF(0, 0, width, height / 2) + painter.drawText( + text_rect, + Qt.AlignmentFlag.AlignCenter | Qt.TextFlag.TextWordWrap, + self._label, + ) + + # Make the signal value text be placed in the lower half of + # the signal viewer rather than in the middle + value_y_start = height / 2 # Draw signal value - # TODO: Proper positioning on the y-axis - text_pos = QPointF(0, value_height_offset) - painter.setPen(palette.text().color()) - painter.setBrush(palette.text()) - painter.drawText(text_pos, str(self._signal.get_value())) + text_rect = QRectF(0, value_y_start, width, height - value_y_start) + painter.drawText( + text_rect, + Qt.AlignmentFlag.AlignCenter | Qt.TextFlag.TextWordWrap, + str(self._signal.get_value()), + ) painter.restore() @Slot() def update(self, rect: QRectF | None = None): + # This "override" is needed in order to decorate update() as a + # pyqt slot super().update() def shape(self) -> QPainterPath: path = QPainterPath() - path.addRect(0, 0, self._width, self._height) - # outline_painter = QPainterPathStroker() - # outline_painter.setWidth(self.outline_width) - # return outline_painter.createStroke(path) + path.addRect(0, 0, self.size().width(), self.size().height()) return path def boundingRect(self) -> QRectF: - return QRectF(0, 0, self._width, self._height) + width = self.size().width() + height = self.size().height() + margin = self.outline_width / 2 + return QRectF(0 - margin, 0 - margin, width + margin, height + margin) + + def outline_width(self) -> float: + return self._outline_width + + def set_outline_width(self, width: float) -> None: + self._outline_width = width + + def outline(self) -> QColor: + return self._outline + + def set_outline(self, color: QColor) -> None: + self._outline = color + + def background(self) -> QColor: + return self._background + + def set_background(self, color: QColor) -> None: + self._background = color + + def text_color(self) -> QColor: + return self._text_color + + def set_text_color(self, color: QColor) -> None: + self._text_color = color + + def text_font(self) -> QFont: + return self._text_font + + def set_text_font(self, font: QFont) -> None: + self._text_font = font + + outline_width = Property(float, outline_width, set_outline_width) + outline = Property(QBrush, outline, set_outline) + background = Property(QBrush, background, set_background) + text_color = Property(QColor, text_color, set_text_color) + text_font = Property(QFont, text_font, set_text_font) diff --git a/src/simudator/processor/mia/mia.py b/src/simudator/processor/mia/mia.py index eb89efe3adf5197f7621593bb7c57d7bd787a401..20605b4585432f3130f474e63bd6a17b0053be5c 100644 --- a/src/simudator/processor/mia/mia.py +++ b/src/simudator/processor/mia/mia.py @@ -335,6 +335,7 @@ class MIA_CPU(Processor): ar = self.get_module("AR") hr = self.get_module("HR") grx = self.get_module("GRx") + lc = self.get_module("LC") bus_signal_pairs = [ (asr.signals["in_content"], None), @@ -372,6 +373,8 @@ class MIA_CPU(Processor): widget = FlagGraphicsItem(module) gui.add_module_graphics_item(widget) + gui.add_signal_viewer(lc.signals["out_flag_l"], "L") + memory_modules = ["PM", "K1", "K2"] for name in memory_modules: module = self.get_module(name)