# Copyright (c) 2018 Ultimaker B.V. # Cura is released under the terms of the LGPLv3 or higher. from cura.CuraApplication import CuraApplication from UM.Settings.DefinitionContainer import DefinitionContainer from cura.MachineAction import MachineAction from UM.i18n import i18nCatalog from UM.Settings.ContainerRegistry import ContainerRegistry from cura.PrinterOutput.FirmwareUpdater import FirmwareUpdateState from PyQt6.QtCore import pyqtSignal, pyqtProperty, QObject from typing import Optional MYPY = False if MYPY: from cura.PrinterOutput.FirmwareUpdater import FirmwareUpdater from cura.PrinterOutput.PrinterOutputDevice import PrinterOutputDevice from UM.Settings.ContainerInterface import ContainerInterface catalog = i18nCatalog("cura") class FirmwareUpdaterMachineAction(MachineAction): """Upgrade the firmware of a machine by USB with this action.""" def __init__(self) -> None: super().__init__("UpgradeFirmware", catalog.i18nc("@action", "Update Firmware")) self._qml_url = "FirmwareUpdaterMachineAction.qml" ContainerRegistry.getInstance().containerAdded.connect(self._onContainerAdded) self._active_output_device = None # type: Optional[PrinterOutputDevice] self._active_firmware_updater = None # type: Optional[FirmwareUpdater] CuraApplication.getInstance().engineCreatedSignal.connect(self._onEngineCreated) def _onEngineCreated(self) -> None: CuraApplication.getInstance().getMachineManager().outputDevicesChanged.connect(self._onOutputDevicesChanged) def _onContainerAdded(self, container: "ContainerInterface") -> None: # Add this action as a supported action to all machine definitions if they support USB connection if isinstance(container, DefinitionContainer) and container.getMetaDataEntry("type") == "machine" and container.getMetaDataEntry("supports_usb_connection"): CuraApplication.getInstance().getMachineActionManager().addSupportedAction(container.getId(), self.getKey()) def _onOutputDevicesChanged(self) -> None: if self._active_output_device and self._active_output_device.activePrinter: self._active_output_device.activePrinter.getController().canUpdateFirmwareChanged.disconnect(self._onControllerCanUpdateFirmwareChanged) output_devices = CuraApplication.getInstance().getMachineManager().printerOutputDevices self._active_output_device = output_devices[0] if output_devices else None if self._active_output_device and self._active_output_device.activePrinter: self._active_output_device.activePrinter.getController().canUpdateFirmwareChanged.connect(self._onControllerCanUpdateFirmwareChanged) self.outputDeviceCanUpdateFirmwareChanged.emit() def _onControllerCanUpdateFirmwareChanged(self) -> None: self.outputDeviceCanUpdateFirmwareChanged.emit() outputDeviceCanUpdateFirmwareChanged = pyqtSignal() @pyqtProperty(QObject, notify = outputDeviceCanUpdateFirmwareChanged) def firmwareUpdater(self) -> Optional["FirmwareUpdater"]: if self._active_output_device and self._active_output_device.activePrinter and self._active_output_device.activePrinter.getController() is not None and self._active_output_device.activePrinter.getController().can_update_firmware: self._active_firmware_updater = self._active_output_device.getFirmwareUpdater() return self._active_firmware_updater elif self._active_firmware_updater and self._active_firmware_updater.firmwareUpdateState not in [FirmwareUpdateState.idle, FirmwareUpdateState.completed]: # During a firmware update, the PrinterOutputDevice is disconnected but the FirmwareUpdater is still there return self._active_firmware_updater self._active_firmware_updater = None return None