Source code for layerview.app.main_window.dto

from __future__ import annotations

from dataclasses import dataclass
from functools import partial
from typing import Any, Generator, Optional, Union

from panda3d.core import LVector3d
from PIL import Image
from PIL.ImageQt import ImageQt
from PyQt5.QtGui import QPixmap

from layerview.app.constants import UNIT_DEGREES_CELSIUS, UNIT_MM, UNIT_MM_PER_MIN
from layerview.visualization.point_cloud.model import LayerInfo, ModelInfo
from layerview.visualization.world.world import ColoringMode

round_2 = partial(round, ndigits=2)


[docs]class IntRangeDTO: def __init__(self, start: int, stop: int): if not all( isinstance(elem, int) or isinstance(elem, float) for elem in [start, stop] ): raise TypeError( f"Expecting start and stop to be of type " f"{int} or {float}, got {type(start)}, {type(stop)}." ) if stop < start: raise ValueError(f"Start ({start}) must not be greater than stop ({stop}).") self.start = start self.stop = stop def __iter__(self) -> Generator[int, Any, None]: return (elem for elem in (self.start, self.stop)) def __repr__(self) -> str: return f"{self.__class__.__name__}(start={self.start}, stop={self.stop})"
[docs]@dataclass class ModelInfoDTO: text_layer_count: str text_height: str text_width: str text_depth: str
[docs] @staticmethod def null_object() -> ModelInfoDTO: return ModelInfoDTO( text_layer_count="", text_height="", text_width="", text_depth="" )
[docs] @staticmethod def from_model_info(model_info: ModelInfo) -> ModelInfoDTO: text_layer_count = str(model_info.layer_count) size: LVector3d = model_info.boundaries.size text_height: str = f"{round_2(size.z)}{UNIT_MM}" text_width: str = f"{round_2(size.x)}{UNIT_MM}" text_depth: str = f"{round_2(size.y)}{UNIT_MM}" dto = ModelInfoDTO( text_layer_count=text_layer_count, text_height=text_height, text_width=text_width, text_depth=text_depth, ) return dto
[docs]@dataclass class LayerInfoDTO: layer_number: int text_z_pos: str text_thickness: str text_temperature: str text_feedrate: str
[docs] @staticmethod def null_object() -> LayerInfoDTO: dto: LayerInfoDTO = LayerInfoDTO( layer_number=0, text_z_pos="", text_thickness="", text_temperature="", text_feedrate="", ) return dto
[docs] @staticmethod def from_layer_info( layer_info: LayerInfo, layer_num: int, z_position: float, height: float ) -> LayerInfoDTO: # Prepare DTO fields text_z_pos: str = ( f"{round_2(z_position)}{UNIT_MM}" if z_position is not None else "" ) text_thickness: str = ( f"{round_2(height)}{UNIT_MM}" if height is not None else "" ) if ( layer_info.temperature_max is not None and layer_info.temperature_min is not None ): text_temp_min: str = str(round_2(layer_info.temperature_min)) text_temp_max: str = str(round_2(layer_info.temperature_max)) text_temperature: str = ( f"{text_temp_min}" if text_temp_min == text_temp_max else f"{text_temp_min}-{text_temp_max}" ) + UNIT_DEGREES_CELSIUS else: text_temperature: str = "" if layer_info.feedrate_min is not None and layer_info is not None: text_feedrate_min: str = str(round_2(layer_info.feedrate_min)) text_feedrate_max: str = str(round_2(layer_info.feedrate_max)) text_feedrate: str = ( f"{text_feedrate_min}" if text_feedrate_min == text_feedrate_max else f"{text_feedrate_min}-{text_feedrate_max}" ) + UNIT_MM_PER_MIN else: text_feedrate: str = "" # Compose DTO dto = LayerInfoDTO( layer_number=layer_num, text_z_pos=text_z_pos, text_thickness=text_thickness, text_temperature=text_temperature, text_feedrate=text_feedrate, ) return dto
[docs]@dataclass class ColoringGroupDTO: coloring_mode: ColoringMode pixmap: QPixmap text_left: str = "" text_center: str = "" text_right: str = "" def __init__( self, coloring_mode: ColoringMode, pixmap: Optional[QPixmap] = None, text_left: Optional[str] = "", text_center: Optional[str] = "", text_right: Optional[str] = "", ): self.coloring_mode: ColoringMode = coloring_mode if not pixmap: q_image = ImageQt( Image.new(mode="RGBA", size=(1, 1), color=(255, 255, 255, 255)) ) pixmap = QPixmap.fromImage(q_image) self.pixmap: QPixmap = pixmap self.text_left = text_left self.text_center = text_center self.text_right = text_right
[docs]class StatusBarMessageDTO: def __init__(self, text: str, duration: int = 0): """ Parameters ---------- text : str The text to display on status bar duration : int Text display duration. Set 0 for infinite duration. """ self.text = text if not isinstance(duration, int): raise TypeError( f"Expected duration to be of type {int}, got {type(duration)}." ) if duration < 0: raise ValueError(f"Duration must be a non-negative int, got {duration}.") self.duration = duration def __iter__(self) -> Generator[Union[str, int], Any, None]: return (elem for elem in (self.text, self.duration)) def __repr__(self) -> str: return f"{self.__class__.__name__}(text={self.text}, duration={self.duration})"