|
@@ -2,7 +2,7 @@
|
|
|
# Cura is released under the terms of the LGPLv3 or higher.
|
|
|
|
|
|
from PyQt5.QtCore import pyqtSignal, pyqtProperty, QObject, QVariant, pyqtSlot
|
|
|
-from typing import Optional
|
|
|
+from typing import List, Dict, Optional
|
|
|
from UM.Math.Vector import Vector
|
|
|
from cura.PrinterOutput.ConfigurationModel import ConfigurationModel
|
|
|
from cura.PrinterOutput.ExtruderOutputModel import ExtruderOutputModel
|
|
@@ -11,6 +11,7 @@ MYPY = False
|
|
|
if MYPY:
|
|
|
from cura.PrinterOutput.PrintJobOutputModel import PrintJobOutputModel
|
|
|
from cura.PrinterOutput.PrinterOutputController import PrinterOutputController
|
|
|
+ from cura.PrinterOutput.NetworkCamera import NetworkCamera
|
|
|
|
|
|
|
|
|
class PrinterOutputModel(QObject):
|
|
@@ -26,6 +27,7 @@ class PrinterOutputModel(QObject):
|
|
|
buildplateChanged = pyqtSignal()
|
|
|
cameraChanged = pyqtSignal()
|
|
|
configurationChanged = pyqtSignal()
|
|
|
+ canUpdateFirmwareChanged = pyqtSignal()
|
|
|
|
|
|
def __init__(self, output_controller: "PrinterOutputController", number_of_extruders: int = 1, parent=None, firmware_version = "") -> None:
|
|
|
super().__init__(parent)
|
|
@@ -34,6 +36,7 @@ class PrinterOutputModel(QObject):
|
|
|
self._name = ""
|
|
|
self._key = "" # Unique identifier
|
|
|
self._controller = output_controller
|
|
|
+ self._controller.canUpdateFirmwareChanged.connect(self._onControllerCanUpdateFirmwareChanged)
|
|
|
self._extruders = [ExtruderOutputModel(printer = self, position = i) for i in range(number_of_extruders)]
|
|
|
self._printer_configuration = ConfigurationModel() # Indicates the current configuration setup in this printer
|
|
|
self._head_position = Vector(0, 0, 0)
|
|
@@ -42,7 +45,7 @@ class PrinterOutputModel(QObject):
|
|
|
self._printer_state = "unknown"
|
|
|
self._is_preheating = False
|
|
|
self._printer_type = ""
|
|
|
- self._buildplate_name = None
|
|
|
+ self._buildplate_name = ""
|
|
|
|
|
|
self._printer_configuration.extruderConfigurations = [extruder.extruderConfiguration for extruder in
|
|
|
self._extruders]
|
|
@@ -50,32 +53,32 @@ class PrinterOutputModel(QObject):
|
|
|
self._camera = None
|
|
|
|
|
|
@pyqtProperty(str, constant = True)
|
|
|
- def firmwareVersion(self):
|
|
|
+ def firmwareVersion(self) -> str:
|
|
|
return self._firmware_version
|
|
|
|
|
|
- def setCamera(self, camera):
|
|
|
+ def setCamera(self, camera: Optional["NetworkCamera"]) -> None:
|
|
|
if self._camera is not camera:
|
|
|
self._camera = camera
|
|
|
self.cameraChanged.emit()
|
|
|
|
|
|
- def updateIsPreheating(self, pre_heating):
|
|
|
+ def updateIsPreheating(self, pre_heating: bool) -> None:
|
|
|
if self._is_preheating != pre_heating:
|
|
|
self._is_preheating = pre_heating
|
|
|
self.isPreheatingChanged.emit()
|
|
|
|
|
|
@pyqtProperty(bool, notify=isPreheatingChanged)
|
|
|
- def isPreheating(self):
|
|
|
+ def isPreheating(self) -> bool:
|
|
|
return self._is_preheating
|
|
|
|
|
|
@pyqtProperty(QObject, notify=cameraChanged)
|
|
|
- def camera(self):
|
|
|
+ def camera(self) -> Optional["NetworkCamera"]:
|
|
|
return self._camera
|
|
|
|
|
|
@pyqtProperty(str, notify = printerTypeChanged)
|
|
|
- def type(self):
|
|
|
+ def type(self) -> str:
|
|
|
return self._printer_type
|
|
|
|
|
|
- def updateType(self, printer_type):
|
|
|
+ def updateType(self, printer_type: str) -> None:
|
|
|
if self._printer_type != printer_type:
|
|
|
self._printer_type = printer_type
|
|
|
self._printer_configuration.printerType = self._printer_type
|
|
@@ -83,10 +86,10 @@ class PrinterOutputModel(QObject):
|
|
|
self.configurationChanged.emit()
|
|
|
|
|
|
@pyqtProperty(str, notify = buildplateChanged)
|
|
|
- def buildplate(self):
|
|
|
+ def buildplate(self) -> str:
|
|
|
return self._buildplate_name
|
|
|
|
|
|
- def updateBuildplateName(self, buildplate_name):
|
|
|
+ def updateBuildplateName(self, buildplate_name: str) -> None:
|
|
|
if self._buildplate_name != buildplate_name:
|
|
|
self._buildplate_name = buildplate_name
|
|
|
self._printer_configuration.buildplateConfiguration = self._buildplate_name
|
|
@@ -94,66 +97,66 @@ class PrinterOutputModel(QObject):
|
|
|
self.configurationChanged.emit()
|
|
|
|
|
|
@pyqtProperty(str, notify=keyChanged)
|
|
|
- def key(self):
|
|
|
+ def key(self) -> str:
|
|
|
return self._key
|
|
|
|
|
|
- def updateKey(self, key: str):
|
|
|
+ def updateKey(self, key: str) -> None:
|
|
|
if self._key != key:
|
|
|
self._key = key
|
|
|
self.keyChanged.emit()
|
|
|
|
|
|
@pyqtSlot()
|
|
|
- def homeHead(self):
|
|
|
+ def homeHead(self) -> None:
|
|
|
self._controller.homeHead(self)
|
|
|
|
|
|
@pyqtSlot()
|
|
|
- def homeBed(self):
|
|
|
+ def homeBed(self) -> None:
|
|
|
self._controller.homeBed(self)
|
|
|
|
|
|
@pyqtSlot(str)
|
|
|
- def sendRawCommand(self, command: str):
|
|
|
+ def sendRawCommand(self, command: str) -> None:
|
|
|
self._controller.sendRawCommand(self, command)
|
|
|
|
|
|
@pyqtProperty("QVariantList", constant = True)
|
|
|
- def extruders(self):
|
|
|
+ def extruders(self) -> List["ExtruderOutputModel"]:
|
|
|
return self._extruders
|
|
|
|
|
|
@pyqtProperty(QVariant, notify = headPositionChanged)
|
|
|
- def headPosition(self):
|
|
|
+ def headPosition(self) -> Dict[str, float]:
|
|
|
return {"x": self._head_position.x, "y": self._head_position.y, "z": self.head_position.z}
|
|
|
|
|
|
- def updateHeadPosition(self, x, y, z):
|
|
|
+ def updateHeadPosition(self, x: float, y: float, z: float) -> None:
|
|
|
if self._head_position.x != x or self._head_position.y != y or self._head_position.z != z:
|
|
|
self._head_position = Vector(x, y, z)
|
|
|
self.headPositionChanged.emit()
|
|
|
|
|
|
@pyqtProperty(float, float, float)
|
|
|
@pyqtProperty(float, float, float, float)
|
|
|
- def setHeadPosition(self, x, y, z, speed = 3000):
|
|
|
+ def setHeadPosition(self, x: float, y: float, z: float, speed: float = 3000) -> None:
|
|
|
self.updateHeadPosition(x, y, z)
|
|
|
self._controller.setHeadPosition(self, x, y, z, speed)
|
|
|
|
|
|
@pyqtProperty(float)
|
|
|
@pyqtProperty(float, float)
|
|
|
- def setHeadX(self, x, speed = 3000):
|
|
|
+ def setHeadX(self, x: float, speed: float = 3000) -> None:
|
|
|
self.updateHeadPosition(x, self._head_position.y, self._head_position.z)
|
|
|
self._controller.setHeadPosition(self, x, self._head_position.y, self._head_position.z, speed)
|
|
|
|
|
|
@pyqtProperty(float)
|
|
|
@pyqtProperty(float, float)
|
|
|
- def setHeadY(self, y, speed = 3000):
|
|
|
+ def setHeadY(self, y: float, speed: float = 3000) -> None:
|
|
|
self.updateHeadPosition(self._head_position.x, y, self._head_position.z)
|
|
|
self._controller.setHeadPosition(self, self._head_position.x, y, self._head_position.z, speed)
|
|
|
|
|
|
@pyqtProperty(float)
|
|
|
@pyqtProperty(float, float)
|
|
|
- def setHeadZ(self, z, speed = 3000):
|
|
|
+ def setHeadZ(self, z: float, speed:float = 3000) -> None:
|
|
|
self.updateHeadPosition(self._head_position.x, self._head_position.y, z)
|
|
|
self._controller.setHeadPosition(self, self._head_position.x, self._head_position.y, z, speed)
|
|
|
|
|
|
@pyqtSlot(float, float, float)
|
|
|
@pyqtSlot(float, float, float, float)
|
|
|
- def moveHead(self, x = 0, y = 0, z = 0, speed = 3000):
|
|
|
+ def moveHead(self, x: float = 0, y: float = 0, z: float = 0, speed: float = 3000) -> None:
|
|
|
self._controller.moveHead(self, x, y, z, speed)
|
|
|
|
|
|
## Pre-heats the heated bed of the printer.
|
|
@@ -162,47 +165,47 @@ class PrinterOutputModel(QObject):
|
|
|
# Celsius.
|
|
|
# \param duration How long the bed should stay warm, in seconds.
|
|
|
@pyqtSlot(float, float)
|
|
|
- def preheatBed(self, temperature, duration):
|
|
|
+ def preheatBed(self, temperature: float, duration: float) -> None:
|
|
|
self._controller.preheatBed(self, temperature, duration)
|
|
|
|
|
|
@pyqtSlot()
|
|
|
- def cancelPreheatBed(self):
|
|
|
+ def cancelPreheatBed(self) -> None:
|
|
|
self._controller.cancelPreheatBed(self)
|
|
|
|
|
|
- def getController(self):
|
|
|
+ def getController(self) -> "PrinterOutputController":
|
|
|
return self._controller
|
|
|
|
|
|
- @pyqtProperty(str, notify=nameChanged)
|
|
|
- def name(self):
|
|
|
+ @pyqtProperty(str, notify = nameChanged)
|
|
|
+ def name(self) -> str:
|
|
|
return self._name
|
|
|
|
|
|
- def setName(self, name):
|
|
|
+ def setName(self, name: str) -> None:
|
|
|
self._setName(name)
|
|
|
self.updateName(name)
|
|
|
|
|
|
- def updateName(self, name):
|
|
|
+ def updateName(self, name: str) -> None:
|
|
|
if self._name != name:
|
|
|
self._name = name
|
|
|
self.nameChanged.emit()
|
|
|
|
|
|
## Update the bed temperature. This only changes it locally.
|
|
|
- def updateBedTemperature(self, temperature):
|
|
|
+ def updateBedTemperature(self, temperature: int) -> None:
|
|
|
if self._bed_temperature != temperature:
|
|
|
self._bed_temperature = temperature
|
|
|
self.bedTemperatureChanged.emit()
|
|
|
|
|
|
- def updateTargetBedTemperature(self, temperature):
|
|
|
+ def updateTargetBedTemperature(self, temperature: int) -> None:
|
|
|
if self._target_bed_temperature != temperature:
|
|
|
self._target_bed_temperature = temperature
|
|
|
self.targetBedTemperatureChanged.emit()
|
|
|
|
|
|
## Set the target bed temperature. This ensures that it's actually sent to the remote.
|
|
|
@pyqtSlot(int)
|
|
|
- def setTargetBedTemperature(self, temperature):
|
|
|
+ def setTargetBedTemperature(self, temperature: int) -> None:
|
|
|
self._controller.setTargetBedTemperature(self, temperature)
|
|
|
self.updateTargetBedTemperature(temperature)
|
|
|
|
|
|
- def updateActivePrintJob(self, print_job):
|
|
|
+ def updateActivePrintJob(self, print_job: Optional["PrintJobOutputModel"]) -> None:
|
|
|
if self._active_print_job != print_job:
|
|
|
old_print_job = self._active_print_job
|
|
|
|
|
@@ -214,72 +217,83 @@ class PrinterOutputModel(QObject):
|
|
|
old_print_job.updateAssignedPrinter(None)
|
|
|
self.activePrintJobChanged.emit()
|
|
|
|
|
|
- def updateState(self, printer_state):
|
|
|
+ def updateState(self, printer_state: str) -> None:
|
|
|
if self._printer_state != printer_state:
|
|
|
self._printer_state = printer_state
|
|
|
self.stateChanged.emit()
|
|
|
|
|
|
@pyqtProperty(QObject, notify = activePrintJobChanged)
|
|
|
- def activePrintJob(self):
|
|
|
+ def activePrintJob(self) -> Optional["PrintJobOutputModel"]:
|
|
|
return self._active_print_job
|
|
|
|
|
|
@pyqtProperty(str, notify=stateChanged)
|
|
|
- def state(self):
|
|
|
+ def state(self) -> str:
|
|
|
return self._printer_state
|
|
|
|
|
|
- @pyqtProperty(int, notify = bedTemperatureChanged)
|
|
|
- def bedTemperature(self):
|
|
|
+ @pyqtProperty(int, notify=bedTemperatureChanged)
|
|
|
+ def bedTemperature(self) -> int:
|
|
|
return self._bed_temperature
|
|
|
|
|
|
@pyqtProperty(int, notify=targetBedTemperatureChanged)
|
|
|
- def targetBedTemperature(self):
|
|
|
+ def targetBedTemperature(self) -> int:
|
|
|
return self._target_bed_temperature
|
|
|
|
|
|
# Does the printer support pre-heating the bed at all
|
|
|
@pyqtProperty(bool, constant=True)
|
|
|
- def canPreHeatBed(self):
|
|
|
+ def canPreHeatBed(self) -> bool:
|
|
|
if self._controller:
|
|
|
return self._controller.can_pre_heat_bed
|
|
|
return False
|
|
|
|
|
|
# Does the printer support pre-heating the bed at all
|
|
|
@pyqtProperty(bool, constant=True)
|
|
|
- def canPreHeatHotends(self):
|
|
|
+ def canPreHeatHotends(self) -> bool:
|
|
|
if self._controller:
|
|
|
return self._controller.can_pre_heat_hotends
|
|
|
return False
|
|
|
|
|
|
# Does the printer support sending raw G-code at all
|
|
|
@pyqtProperty(bool, constant=True)
|
|
|
- def canSendRawGcode(self):
|
|
|
+ def canSendRawGcode(self) -> bool:
|
|
|
if self._controller:
|
|
|
return self._controller.can_send_raw_gcode
|
|
|
return False
|
|
|
|
|
|
# Does the printer support pause at all
|
|
|
@pyqtProperty(bool, constant=True)
|
|
|
- def canPause(self):
|
|
|
+ def canPause(self) -> bool:
|
|
|
if self._controller:
|
|
|
return self._controller.can_pause
|
|
|
return False
|
|
|
|
|
|
# Does the printer support abort at all
|
|
|
@pyqtProperty(bool, constant=True)
|
|
|
- def canAbort(self):
|
|
|
+ def canAbort(self) -> bool:
|
|
|
if self._controller:
|
|
|
return self._controller.can_abort
|
|
|
return False
|
|
|
|
|
|
# Does the printer support manual control at all
|
|
|
@pyqtProperty(bool, constant=True)
|
|
|
- def canControlManually(self):
|
|
|
+ def canControlManually(self) -> bool:
|
|
|
if self._controller:
|
|
|
return self._controller.can_control_manually
|
|
|
return False
|
|
|
|
|
|
+ # Does the printer support upgrading firmware
|
|
|
+ @pyqtProperty(bool, notify = canUpdateFirmwareChanged)
|
|
|
+ def canUpdateFirmware(self) -> bool:
|
|
|
+ if self._controller:
|
|
|
+ return self._controller.can_update_firmware
|
|
|
+ return False
|
|
|
+
|
|
|
+ # Stub to connect UM.Signal to pyqtSignal
|
|
|
+ def _onControllerCanUpdateFirmwareChanged(self) -> None:
|
|
|
+ self.canUpdateFirmwareChanged.emit()
|
|
|
+
|
|
|
# Returns the configuration (material, variant and buildplate) of the current printer
|
|
|
@pyqtProperty(QObject, notify = configurationChanged)
|
|
|
- def printerConfiguration(self):
|
|
|
+ def printerConfiguration(self) -> Optional[ConfigurationModel]:
|
|
|
if self._printer_configuration.isValid():
|
|
|
return self._printer_configuration
|
|
|
return None
|