From c2b9c5def78dfdd9a9ab02dc4fe3f54cec579bcd Mon Sep 17 00:00:00 2001 From: Jonathan Perret Date: Sun, 22 Sep 2024 23:44:18 +0200 Subject: [PATCH] Fix "default knit side image" behavior Instead of Scene modifying AyabImage's internal image, it now reverses the image (if requested) only at render time. This makes it easier to avoid getting confused with how many times the image has been reversed. --- src/main/python/main/ayab/ayab.py | 4 ---- src/main/python/main/ayab/engine/options.py | 11 ++++++---- src/main/python/main/ayab/engine/pattern.py | 4 +++- src/main/python/main/ayab/image.py | 1 - src/main/python/main/ayab/scene.py | 21 +++++++------------ src/main/python/main/ayab/signal_receiver.py | 4 ++-- src/main/python/main/ayab/signal_sender.py | 4 ++-- .../python/main/ayab/tests/test_control.py | 3 ++- 8 files changed, 24 insertions(+), 28 deletions(-) diff --git a/src/main/python/main/ayab/ayab.py b/src/main/python/main/ayab/ayab.py index 46fee3a8..2bde0477 100644 --- a/src/main/python/main/ayab/ayab.py +++ b/src/main/python/main/ayab/ayab.py @@ -185,10 +185,6 @@ def set_image_dimensions(self) -> None: ) self.scene.refresh() - def reverse_image(self) -> None: - """Flip image horizontally.""" - self.scene.reverse() - def update_start_row(self, start_row: int) -> None: self.scene.row_progress = start_row self.engine.status.current_row = start_row diff --git a/src/main/python/main/ayab/engine/options.py b/src/main/python/main/ayab/engine/options.py index 46f73abf..be6e0d2c 100644 --- a/src/main/python/main/ayab/engine/options.py +++ b/src/main/python/main/ayab/engine/options.py @@ -82,6 +82,7 @@ class OptionsTab(SignalSender, QWidget): def __init__(self, parent: GuiMain): super().__init__(parent.signal_receiver) self.prefs = parent.prefs + self.auto_mirror = False self.ui = Ui_Options() self.__setup_ui() self.__activate_ui() @@ -113,7 +114,7 @@ def __activate_ui(self) -> None: self.ui.alignment_combo_box.currentIndexChanged.connect( lambda: self.emit_alignment_updater(self.__read_alignment()) ) - self.ui.auto_mirror_checkbox.clicked.connect(self.__reverse_image) + self.ui.auto_mirror_checkbox.clicked.connect(self.__auto_mirror_changed) def update_needles(self) -> None: """Sends the needles_updater signal.""" @@ -122,14 +123,15 @@ def update_needles(self) -> None: stop_needle = NeedleColor.read_stop_needle(self.ui, self.machine) self.emit_needles_updater(start_needle, stop_needle) - def __reverse_image(self) -> None: - if self.ui.auto_mirror_checkbox.isChecked(): + def __auto_mirror_changed(self) -> None: + image_reversed = self.ui.auto_mirror_checkbox.isChecked() + if image_reversed: self.ui.auto_mirror_icon.setPixmap(QPixmap(":/garamond-lowercase-e.png")) else: self.ui.auto_mirror_icon.setPixmap( QPixmap(":/garamond-lowercase-e-reversed.png") ) - self.emit_image_reverser() + self.emit_image_reverser(image_reversed) def __read_start_row(self) -> int: return int(self.ui.start_row_edit.value()) - 1 @@ -185,6 +187,7 @@ def refresh(self) -> None: QPixmap(":/garamond-lowercase-e-reversed.png") ) # self.ui.continuous_reporting_checkbox + self.emit_image_reverser(self.auto_mirror) def as_dict(self) -> OptionsTabDict: return OptionsTabDict( diff --git a/src/main/python/main/ayab/engine/pattern.py b/src/main/python/main/ayab/engine/pattern.py index b50f0cf1..3fecdda0 100644 --- a/src/main/python/main/ayab/engine/pattern.py +++ b/src/main/python/main/ayab/engine/pattern.py @@ -31,7 +31,9 @@ class Pattern(object): def __init__(self, image: Image.Image, config: OptionsTab, num_colors: int = 2): - self.__pattern = image + self.__pattern = ( + image.transpose(Image.FLIP_LEFT_RIGHT) if config.auto_mirror else image + ) self.__num_colors = num_colors self.__alignment = Alignment.CENTER self.__pat_start_needle: int = -1 diff --git a/src/main/python/main/ayab/image.py b/src/main/python/main/ayab/image.py index aa5c3c77..0259357f 100644 --- a/src/main/python/main/ayab/image.py +++ b/src/main/python/main/ayab/image.py @@ -56,7 +56,6 @@ def __init__(self, parent: GuiMain): self.__parent = parent self.image: Image.Image = None # type: ignore self.filename: Optional[str] = None - self.reversed = False self.filename_input = self.__parent.ui.filename_lineedit def select_file(self) -> None: diff --git a/src/main/python/main/ayab/scene.py b/src/main/python/main/ayab/scene.py index aab7630e..6157a86c 100644 --- a/src/main/python/main/ayab/scene.py +++ b/src/main/python/main/ayab/scene.py @@ -23,7 +23,7 @@ from enum import Enum from PySide6.QtCore import QRect -from PySide6.QtGui import QImage, QPixmap, QPen, QBrush, QColor, QWheelEvent +from PySide6.QtGui import QImage, QPixmap, QPen, QBrush, QColor, QWheelEvent, QTransform from PySide6.QtWidgets import ( QGraphicsScene, QGraphicsRectItem, @@ -32,7 +32,6 @@ ) from .image import AyabImage -from .transforms import Transform from .engine.options import Alignment from .machine import Machine from typing import TYPE_CHECKING @@ -69,23 +68,17 @@ def __init__(self, parent: GuiMain): self.__start_needle: int = (machine_width // 2) - 20 self.__stop_needle: int = (machine_width - 1) // 2 + 20 self.__row_progress: int = 0 + self.image_reversed = False # zoom behavior self.setDragMode(QGraphicsView.DragMode.ScrollHandDrag) self.__zoom: float = 3 - self.ayabimage.reversed = False - if self.__prefs.value("default_knit_side_image"): - self.reverse() # calls refresh(), so no need to call it again - else: - self.refresh() - - def reverse(self) -> None: - """Mirrors the image""" + self.refresh() - if self.ayabimage.image is not None: - self.ayabimage.reversed = not self.ayabimage.reversed - self.ayabimage.image = Transform.hflip(self.ayabimage.image) + def set_image_reversed(self, image_reversed: bool) -> None: + """Sets the image reversed flag""" + self.image_reversed = image_reversed self.refresh() @@ -110,6 +103,8 @@ def refresh(self) -> None: width, height = self.ayabimage.image.size data = self.ayabimage.image.convert("RGBA").tobytes("raw", "RGBA") qim = QImage(data, width, height, QImage.Format.Format_RGBA8888) + if self.image_reversed: + qim = qim.transformed(QTransform.fromScale(-1, 1)) pixmap = QPixmap.fromImage(qim) # add pattern and locate according to alignment diff --git a/src/main/python/main/ayab/signal_receiver.py b/src/main/python/main/ayab/signal_receiver.py index 95a84357..d3932a79 100644 --- a/src/main/python/main/ayab/signal_receiver.py +++ b/src/main/python/main/ayab/signal_receiver.py @@ -53,7 +53,7 @@ class SignalReceiver(QObject): needles_updater = Signal(int, int) alignment_updater = Signal(Alignment) image_resizer = Signal() - image_reverser = Signal() + image_reverser = Signal(bool) got_image_flag = Signal() new_image_flag = Signal() bad_config_flag = Signal() @@ -77,7 +77,7 @@ def activate_signals(self, parent: GuiMain) -> None: self.needles_updater.connect(parent.scene.update_needles) self.alignment_updater.connect(parent.scene.update_alignment) self.image_resizer.connect(parent.set_image_dimensions) - self.image_reverser.connect(parent.reverse_image) + self.image_reverser.connect(parent.scene.set_image_reversed) self.operation_finisher.connect(parent.finish_operation) self.hw_test_starter.connect(parent.hw_test.open) self.hw_test_writer.connect(parent.hw_test.output) diff --git a/src/main/python/main/ayab/signal_sender.py b/src/main/python/main/ayab/signal_sender.py index 064caf1e..4dbc2416 100644 --- a/src/main/python/main/ayab/signal_sender.py +++ b/src/main/python/main/ayab/signal_sender.py @@ -86,8 +86,8 @@ def emit_alignment_updater(self, alignment: Alignment) -> None: def emit_image_resizer(self) -> None: self.__signal_receiver.image_resizer.emit() - def emit_image_reverser(self) -> None: - self.__signal_receiver.image_reverser.emit() + def emit_image_reverser(self, image_reversed: bool) -> None: + self.__signal_receiver.image_reverser.emit(image_reversed) def emit_got_image_flag(self) -> None: self.__signal_receiver.got_image_flag.emit() diff --git a/src/main/python/main/ayab/tests/test_control.py b/src/main/python/main/ayab/tests/test_control.py index e4c2f5ad..039eb46e 100644 --- a/src/main/python/main/ayab/tests/test_control.py +++ b/src/main/python/main/ayab/tests/test_control.py @@ -43,9 +43,10 @@ def __init__(self): class Config(object): - def __init__(self, machine, mode=Mode.SINGLEBED): + def __init__(self, machine, mode=Mode.SINGLEBED, auto_mirror=False): self.machine = machine self.mode = mode + self.auto_mirror = auto_mirror class TestControl(unittest.TestCase):