From 1fee23007142f90b9dde08329983f4f03a4a25d5 Mon Sep 17 00:00:00 2001 From: Tomer Shalev Date: Sun, 4 Feb 2024 11:54:32 +0000 Subject: [PATCH] Refactor DymoLabeler classes Fix a bug in which we had a constant for vertical margin, which is not true, since for every label width the margin is different. Remove labeler state from DymoLabelerFunctions (it no longer initialized with current tape size). Store default tape sizes in the labeler class, instead of in the GUI's code. --- src/dymoprint/cli/cli.py | 5 ++- src/dymoprint/gui/gui.py | 19 ++++++----- src/dymoprint/gui/q_dymo_labels_list.py | 9 +++-- src/dymoprint/lib/dymo_labeler.py | 44 ++++++++++++------------- 4 files changed, 42 insertions(+), 35 deletions(-) diff --git a/src/dymoprint/cli/cli.py b/src/dymoprint/cli/cli.py index f11a58c..a432337 100755 --- a/src/dymoprint/cli/cli.py +++ b/src/dymoprint/cli/cli.py @@ -295,17 +295,16 @@ def run(): else None ) + dymo_labeler = DymoLabeler(tape_size_mm=args.tape_size_mm) render_engine = HorizontallyCombinedRenderEngine(render_engines) render_kwargs = dict( render_engine=render_engine, justify=args.justify, visible_horizontal_margin_px=margin_px, - labeler_margin_px=DymoLabeler.get_labeler_margin_px(), + labeler_margin_px=dymo_labeler.labeler_margin_px, max_width_px=max_payload_len_px, min_width_px=min_payload_len_px, ) - - dymo_labeler = DymoLabeler(tape_size_mm=args.tape_size_mm) render_context = RenderContext(height_px=dymo_labeler.height_px) # print or show the label diff --git a/src/dymoprint/gui/gui.py b/src/dymoprint/gui/gui.py index 54caaf1..1eae3f4 100644 --- a/src/dymoprint/gui/gui.py +++ b/src/dymoprint/gui/gui.py @@ -36,9 +36,6 @@ class DymoPrintWindow(QWidget): - SUPPORTED_TAPE_SIZE_MM = (19, 12, 9, 6) - DEFAULT_TAPE_SIZE_MM_INDEX = 1 - print_label_bitmap: Optional[Image.Image] dymo_labeler: DymoLabeler @@ -84,13 +81,19 @@ def init_elements(self): shadow.setBlurRadius(15) self.label_render.setGraphicsEffect(shadow) - h_margins_mm = round(DymoLabeler.LABELER_HORIZONTAL_MARGIN_MM) + self.dymo_labeler = DymoLabeler() + for tape_size_mm in self.dymo_labeler.SUPPORTED_TAPE_SIZES_MM: + self.tape_size_mm.addItem(str(tape_size_mm), tape_size_mm) + tape_size_index = self.dymo_labeler.SUPPORTED_TAPE_SIZES_MM.index( + self.dymo_labeler.tape_size_mm + ) + self.tape_size_mm.setCurrentIndex(tape_size_index) + + h_margins_mm = round(self.dymo_labeler.minimum_horizontal_margin_mm) self.horizontal_margin_mm.setMinimum(h_margins_mm) self.horizontal_margin_mm.setMaximum(100) self.horizontal_margin_mm.setValue(h_margins_mm) - for tape_size_mm in self.SUPPORTED_TAPE_SIZE_MM: - self.tape_size_mm.addItem(str(tape_size_mm), tape_size_mm) - self.tape_size_mm.setCurrentIndex(self.DEFAULT_TAPE_SIZE_MM_INDEX) + self.min_label_width_mm.setMinimum(h_margins_mm * 2) self.min_label_width_mm.setMaximum(300) self.justify.addItems(["center", "left", "right"]) @@ -102,7 +105,6 @@ def init_elements(self): ["white", "black", "yellow", "blue", "red", "green"] ) - self.dymo_labeler = DymoLabeler() self.update_params() self.label_list.populate() @@ -185,6 +187,7 @@ def update_params(self): self.render_context.height_px = self.dymo_labeler.height_px self.label_list.update_params( + dymo_labeler=self.dymo_labeler, h_margin_mm=horizontal_margin_mm, min_label_width_mm=min_label_width_mm, render_context=self.render_context, diff --git a/src/dymoprint/gui/q_dymo_labels_list.py b/src/dymoprint/gui/q_dymo_labels_list.py index bb3c2e5..506cd5c 100644 --- a/src/dymoprint/gui/q_dymo_labels_list.py +++ b/src/dymoprint/gui/q_dymo_labels_list.py @@ -70,12 +70,14 @@ class QDymoLabelList(QListWidget): ) render_context: Optional[RenderContext] itemWidget: TextDymoLabelWidget + dymo_labeler: DymoLabeler h_margin_mm: float min_label_width_mm: Optional[float] justify: str def __init__(self, parent=None): super().__init__(parent) + self.dymo_labeler = None self.margin_px = None self.min_label_width_mm = None self.justify = "center" @@ -103,6 +105,7 @@ def dropEvent(self, e) -> None: def update_params( self, + dymo_labeler: DymoLabeler, h_margin_mm: float, min_label_width_mm: float, render_context: RenderContext, @@ -112,11 +115,13 @@ def update_params( Args: ---- + dymo_labeler: an instance of DymoLabeler object h_margin_mm: horizontal margin [mm] min_label_width_mm: minimum label width [mm] render_context (RenderContext): The new render context to use. justify: justification [center,left,right] """ + self.dymo_labeler = dymo_labeler self.h_margin_mm = h_margin_mm self.min_label_width_mm = min_label_width_mm self.justify = justify @@ -160,7 +165,7 @@ def render_preview(self): render_engine=self._payload_render_engine, justify=self.justify, visible_horizontal_margin_px=mm_to_px(self.h_margin_mm), - labeler_margin_px=DymoLabeler.get_labeler_margin_px(), + labeler_margin_px=self.dymo_labeler.labeler_margin_px, max_width_px=None, min_width_px=mm_to_px(self.min_label_width_mm), ) @@ -177,7 +182,7 @@ def render_print(self): render_engine=self._payload_render_engine, justify=self.justify, visible_horizontal_margin_px=mm_to_px(self.h_margin_mm), - labeler_margin_px=DymoLabeler.get_labeler_margin_px(), + labeler_margin_px=self.dymo_labeler.labeler_margin_px, max_width_px=None, min_width_px=mm_to_px(self.min_label_width_mm), ) diff --git a/src/dymoprint/lib/dymo_labeler.py b/src/dymoprint/lib/dymo_labeler.py index ffff8c1..43f16b7 100755 --- a/src/dymoprint/lib/dymo_labeler.py +++ b/src/dymoprint/lib/dymo_labeler.py @@ -20,7 +20,6 @@ from dymoprint.lib.utils import mm_to_px LOG = logging.getLogger(__name__) -DEFAULT_TAPE_SIZE_MM = 12 POSSIBLE_USB_ERRORS = (DymoUSBError, NoBackendError, USBError) @@ -51,8 +50,6 @@ class DymoLabelerFunctions: """ - tape_size_mm: int - # Max number of print lines to send before waiting for a response. This helps # to avoid timeouts due to differences between data transfer and # printer speeds. I added this because I kept getting "IOError: [Errno @@ -69,10 +66,8 @@ def __init__( devout: usb.core.Endpoint, devin: usb.core.Endpoint, synwait: int | None = None, - tape_size_mm: int | None = None, ): """Initialize the LabelManager object (HLF).""" - self._tape_size_mm = tape_size_mm self._cmd: list[int] = [] self._response = False self._bytesPerLine = None @@ -83,13 +78,11 @@ def __init__( self._synwait = synwait @classmethod - def _max_bytes_per_line(cls, tape_size_mm: int | None = None) -> int: - if not tape_size_mm: - tape_size_mm = DEFAULT_TAPE_SIZE_MM + def _max_bytes_per_line(cls, tape_size_mm: int) -> int: return int(8 * tape_size_mm / 12) @classmethod - def height_px(cls, tape_size_mm: int | None = None): + def height_px(cls, tape_size_mm: int): return cls._max_bytes_per_line(tape_size_mm) * 8 def _send_command(self): @@ -155,9 +148,9 @@ def _status_request(self): self._build_command(cmd) self._response = True - def _dot_tab(self, value): + def _dot_tab(self, value, tape_size_mm: int): """Set the bias text height, in bytes (MLF).""" - if value < 0 or value > self._max_bytes_per_line(self._tape_size_mm): + if value < 0 or value > self._max_bytes_per_line(tape_size_mm): raise ValueError cmd = [ESC, ord("B"), value] self._build_command(cmd) @@ -190,11 +183,11 @@ def _line(self, value): cmd = [SYN, *value] self._build_command(cmd) - def _chain_mark(self): + def _chain_mark(self, tape_size_mm: int): """Set Chain Mark (MLF).""" - self._dot_tab(0) - self._bytes_per_line(self._max_bytes_per_line(self._tape_size_mm)) - self._line([0x99] * self._max_bytes_per_line(self._tape_size_mm)) + self._dot_tab(0, tape_size_mm) + self._bytes_per_line(self._max_bytes_per_line(tape_size_mm)) + self._line([0x99] * self._max_bytes_per_line(tape_size_mm)) def _skip_lines(self, value): """Set number of lines of white to print (MLF).""" @@ -245,13 +238,16 @@ class DymoLabeler: device: DetectedDevice tape_size_mm: int - LABELER_HORIZONTAL_MARGIN_MM = 8.1 - LABELER_VERTICAL_MARGIN_MM = 1.9 + LABELER_DISTANCE_BETWEEN_PRINT_HEAD_AND_CUTTER_MM = 8.1 + LABELER_PRINT_HEAD_HEIGHT_MM = 8.2 + SUPPORTED_TAPE_SIZES_MM = (19, 12, 9, 6) + DEFAULT_TAPE_SIZE_MM = 12 def __init__( self, tape_size_mm: int = DEFAULT_TAPE_SIZE_MM, ): + assert tape_size_mm in self.SUPPORTED_TAPE_SIZES_MM self.tape_size_mm = tape_size_mm self.device = None @@ -268,14 +264,18 @@ def _functions(self): devout=self.device.devout, devin=self.device.devin, synwait=64, - tape_size_mm=self.tape_size_mm, ) - @classmethod - def get_labeler_margin_px(cls) -> tuple[float, float]: + @property + def minimum_horizontal_margin_mm(self): + return self.LABELER_DISTANCE_BETWEEN_PRINT_HEAD_AND_CUTTER_MM + + @property + def labeler_margin_px(self) -> tuple[float, float]: + vertical_margin_mm = (self.tape_size_mm - self.LABELER_PRINT_HEAD_HEIGHT_MM) / 2 return ( - mm_to_px(cls.LABELER_HORIZONTAL_MARGIN_MM), - mm_to_px(cls.LABELER_VERTICAL_MARGIN_MM), + mm_to_px(self.minimum_horizontal_margin_mm), + mm_to_px(vertical_margin_mm), ) def detect(self):