diff --git a/cura/PrinterOutputDevice.py b/cura/PrinterOutputDevice.py index 98ba4a19a8..ab727d723d 100644 --- a/cura/PrinterOutputDevice.py +++ b/cura/PrinterOutputDevice.py @@ -1,17 +1,20 @@ # Copyright (c) 2018 Ultimaker B.V. # Cura is released under the terms of the LGPLv3 or higher. + from UM.Decorators import deprecated from UM.i18n import i18nCatalog from UM.OutputDevice.OutputDevice import OutputDevice -from PyQt5.QtCore import pyqtProperty, QObject, QTimer, pyqtSignal, QVariant +from PyQt5.QtCore import pyqtProperty, QObject, QTimer, pyqtSignal from PyQt5.QtWidgets import QMessageBox from UM.Logger import Logger +from UM.FileHandler.FileHandler import FileHandler #For typing. +from UM.Scene.SceneNode import SceneNode #For typing. from UM.Signal import signalemitter from UM.Application import Application from enum import IntEnum # For the connection state tracking. -from typing import List, Optional +from typing import Callable, List, Optional MYPY = False if MYPY: @@ -20,6 +23,16 @@ if MYPY: i18n_catalog = i18nCatalog("cura") + +## The current processing state of the backend. +class ConnectionState(IntEnum): + closed = 0 + connecting = 1 + connected = 2 + busy = 3 + error = 4 + + ## Printer output device adds extra interface options on top of output device. # # The assumption is made the printer is a FDM printer. @@ -47,38 +60,37 @@ class PrinterOutputDevice(QObject, OutputDevice): # Signal to indicate that the configuration of one of the printers has changed. uniqueConfigurationsChanged = pyqtSignal() - def __init__(self, device_id, parent = None): + def __init__(self, device_id: str, parent: QObject = None) -> None: super().__init__(device_id = device_id, parent = parent) self._printers = [] # type: List[PrinterOutputModel] self._unique_configurations = [] # type: List[ConfigurationModel] - self._monitor_view_qml_path = "" - self._monitor_component = None - self._monitor_item = None + self._monitor_view_qml_path = "" #type: str + self._monitor_component = None #type: Optional[QObject] + self._monitor_item = None #type: Optional[QObject] - self._control_view_qml_path = "" - self._control_component = None - self._control_item = None + self._control_view_qml_path = "" #type: str + self._control_component = None #type: Optional[QObject] + self._control_item = None #type: Optional[QObject] - self._qml_context = None - self._accepts_commands = False + self._accepts_commands = False #type: bool - self._update_timer = QTimer() + self._update_timer = QTimer() #type: QTimer self._update_timer.setInterval(2000) # TODO; Add preference for update interval self._update_timer.setSingleShot(False) self._update_timer.timeout.connect(self._update) - self._connection_state = ConnectionState.closed + self._connection_state = ConnectionState.closed #type: ConnectionState - self._firmware_name = None - self._address = "" - self._connection_text = "" + self._firmware_name = None #type: Optional[str] + self._address = "" #type: str + self._connection_text = "" #type: str self.printersChanged.connect(self._onPrintersChanged) Application.getInstance().getOutputDeviceManager().outputDevicesChanged.connect(self._updateUniqueConfigurations) @pyqtProperty(str, notify = connectionTextChanged) - def address(self): + def address(self) -> str: return self._address def setConnectionText(self, connection_text): @@ -87,36 +99,36 @@ class PrinterOutputDevice(QObject, OutputDevice): self.connectionTextChanged.emit() @pyqtProperty(str, constant=True) - def connectionText(self): + def connectionText(self) -> str: return self._connection_text - def materialHotendChangedMessage(self, callback): + def materialHotendChangedMessage(self, callback: Callable[[int], None]) -> None: Logger.log("w", "materialHotendChangedMessage needs to be implemented, returning 'Yes'") callback(QMessageBox.Yes) - def isConnected(self): + def isConnected(self) -> bool: return self._connection_state != ConnectionState.closed and self._connection_state != ConnectionState.error - def setConnectionState(self, connection_state): + def setConnectionState(self, connection_state: ConnectionState) -> None: if self._connection_state != connection_state: self._connection_state = connection_state self.connectionStateChanged.emit(self._id) @pyqtProperty(str, notify = connectionStateChanged) - def connectionState(self): + def connectionState(self) -> ConnectionState: return self._connection_state - def _update(self): + def _update(self) -> None: pass - def _getPrinterByKey(self, key) -> Optional["PrinterOutputModel"]: + def _getPrinterByKey(self, key: str) -> Optional["PrinterOutputModel"]: for printer in self._printers: if printer.key == key: return printer return None - def requestWrite(self, nodes, file_name = None, filter_by_machine = False, file_handler = None, **kwargs): + def requestWrite(self, nodes: List[SceneNode], file_name: Optional[str] = None, limit_mimetypes: bool = False, file_handler: Optional[FileHandler] = None, **kwargs: str) -> None: raise NotImplementedError("requestWrite needs to be implemented") @pyqtProperty(QObject, notify = printersChanged) @@ -126,11 +138,11 @@ class PrinterOutputDevice(QObject, OutputDevice): return None @pyqtProperty("QVariantList", notify = printersChanged) - def printers(self): + def printers(self) -> List["PrinterOutputModel"]: return self._printers - @pyqtProperty(QObject, constant=True) - def monitorItem(self): + @pyqtProperty(QObject, constant = True) + def monitorItem(self) -> QObject: # Note that we specifically only check if the monitor component is created. # It could be that it failed to actually create the qml item! If we check if the item was created, it will try to # create the item (and fail) every time. @@ -138,19 +150,19 @@ class PrinterOutputDevice(QObject, OutputDevice): self._createMonitorViewFromQML() return self._monitor_item - @pyqtProperty(QObject, constant=True) - def controlItem(self): + @pyqtProperty(QObject, constant = True) + def controlItem(self) -> QObject: if not self._control_component: self._createControlViewFromQML() return self._control_item - def _createControlViewFromQML(self): + def _createControlViewFromQML(self) -> None: if not self._control_view_qml_path: return if self._control_item is None: self._control_item = Application.getInstance().createQmlComponent(self._control_view_qml_path, {"OutputDevice": self}) - def _createMonitorViewFromQML(self): + def _createMonitorViewFromQML(self) -> None: if not self._monitor_view_qml_path: return @@ -158,29 +170,29 @@ class PrinterOutputDevice(QObject, OutputDevice): self._monitor_item = Application.getInstance().createQmlComponent(self._monitor_view_qml_path, {"OutputDevice": self}) ## Attempt to establish connection - def connect(self): + def connect(self) -> None: self.setConnectionState(ConnectionState.connecting) self._update_timer.start() ## Attempt to close the connection - def close(self): + def close(self) -> None: self._update_timer.stop() self.setConnectionState(ConnectionState.closed) ## Ensure that close gets called when object is destroyed - def __del__(self): + def __del__(self) -> None: self.close() - @pyqtProperty(bool, notify=acceptsCommandsChanged) - def acceptsCommands(self): + @pyqtProperty(bool, notify = acceptsCommandsChanged) + def acceptsCommands(self) -> bool: return self._accepts_commands @deprecated("Please use the protected function instead", "3.2") - def setAcceptsCommands(self, accepts_commands): + def setAcceptsCommands(self, accepts_commands: bool) -> None: self._setAcceptsCommands(accepts_commands) ## Set a flag to signal the UI that the printer is not (yet) ready to receive commands - def _setAcceptsCommands(self, accepts_commands): + def _setAcceptsCommands(self, accepts_commands: bool) -> None: if self._accepts_commands != accepts_commands: self._accepts_commands = accepts_commands @@ -188,15 +200,15 @@ class PrinterOutputDevice(QObject, OutputDevice): # Returns the unique configurations of the printers within this output device @pyqtProperty("QVariantList", notify = uniqueConfigurationsChanged) - def uniqueConfigurations(self): + def uniqueConfigurations(self) -> List[ConfigurationModel]: return self._unique_configurations - def _updateUniqueConfigurations(self): + def _updateUniqueConfigurations(self) -> None: self._unique_configurations = list(set([printer.printerConfiguration for printer in self._printers if printer.printerConfiguration is not None])) self._unique_configurations.sort(key = lambda k: k.printerType) self.uniqueConfigurationsChanged.emit() - def _onPrintersChanged(self): + def _onPrintersChanged(self) -> None: for printer in self._printers: printer.configurationChanged.connect(self._updateUniqueConfigurations) @@ -205,21 +217,12 @@ class PrinterOutputDevice(QObject, OutputDevice): ## Set the device firmware name # - # \param name \type{str} The name of the firmware. - def _setFirmwareName(self, name): + # \param name The name of the firmware. + def _setFirmwareName(self, name: str) -> None: self._firmware_name = name ## Get the name of device firmware # # This name can be used to define device type - def getFirmwareName(self): - return self._firmware_name - - -## The current processing state of the backend. -class ConnectionState(IntEnum): - closed = 0 - connecting = 1 - connected = 2 - busy = 3 - error = 4 + def getFirmwareName(self) -> str: + return self._firmware_name \ No newline at end of file