diff --git a/cura/PrinterOutput/FirmwareUpdater.py b/cura/PrinterOutput/FirmwareUpdater.py index 88169b1d75..92e92437ad 100644 --- a/cura/PrinterOutput/FirmwareUpdater.py +++ b/cura/PrinterOutput/FirmwareUpdater.py @@ -3,26 +3,25 @@ from PyQt5.QtCore import QObject, QUrl, pyqtSignal, pyqtProperty -from UM.Resources import Resources -from cura.PrinterOutputDevice import PrinterOutputDevice -from cura.CuraApplication import CuraApplication - from enum import IntEnum from threading import Thread from typing import Union +MYPY = False +if MYPY: + from cura.PrinterOutputDevice import PrinterOutputDevice + class FirmwareUpdater(QObject): firmwareProgressChanged = pyqtSignal() firmwareUpdateStateChanged = pyqtSignal() - def __init__(self, output_device: PrinterOutputDevice) -> None: + def __init__(self, output_device: "PrinterOutputDevice") -> None: super().__init__() self._output_device = output_device self._update_firmware_thread = Thread(target=self._updateFirmware, daemon=True) - self._firmware_view = None self._firmware_location = "" self._firmware_progress = 0 self._firmware_update_state = FirmwareUpdateState.idle @@ -33,7 +32,7 @@ class FirmwareUpdater(QObject): self._firmware_location = QUrl(file).toLocalFile() else: self._firmware_location = file - self._showFirmwareInterface() + self._setFirmwareUpdateState(FirmwareUpdateState.updating) self._update_firmware_thread.start() @@ -41,20 +40,6 @@ class FirmwareUpdater(QObject): def _updateFirmware(self) -> None: raise NotImplementedError("_updateFirmware needs to be implemented") - ## Show firmware interface. - # This will create the view if its not already created. - def _showFirmwareInterface(self) -> None: - if self._firmware_view is None: - path = Resources.getPath(CuraApplication.ResourceTypes.QmlFiles, "FirmwareUpdateWindow.qml") - self._firmware_view = CuraApplication.getInstance().createQmlComponent(path, {"manager": self}) - - if not self._firmware_view: - return - - self._onFirmwareProgress(0) - self._setFirmwareUpdateState(FirmwareUpdateState.idle) - self._firmware_view.show() - ## Cleanup after a succesful update def _cleanupAfterUpdate(self) -> None: # Clean up for next attempt. diff --git a/cura/PrinterOutputDevice.py b/cura/PrinterOutputDevice.py index 5ea65adb8e..c63f9c35b5 100644 --- a/cura/PrinterOutputDevice.py +++ b/cura/PrinterOutputDevice.py @@ -20,6 +20,7 @@ MYPY = False if MYPY: from cura.PrinterOutput.PrinterOutputModel import PrinterOutputModel from cura.PrinterOutput.ConfigurationModel import ConfigurationModel + from cura.PrinterOutput.FirmwareUpdater import FirmwareUpdater i18n_catalog = i18nCatalog("cura") @@ -83,6 +84,7 @@ class PrinterOutputDevice(QObject, OutputDevice): self._connection_state = ConnectionState.closed #type: ConnectionState + self._firmware_updater = None #type: Optional[FirmwareUpdater] self._firmware_name = None #type: Optional[str] self._address = "" #type: str self._connection_text = "" #type: str @@ -225,4 +227,7 @@ class PrinterOutputDevice(QObject, OutputDevice): # # This name can be used to define device type def getFirmwareName(self) -> Optional[str]: - return self._firmware_name \ No newline at end of file + return self._firmware_name + + def getFirmwareUpdater(self) -> Optional["FirmwareUpdater"]: + return self._firmware_updater \ No newline at end of file diff --git a/plugins/UltimakerMachineActions/UpgradeFirmwareMachineAction.py b/plugins/UltimakerMachineActions/UpgradeFirmwareMachineAction.py index 1f0e640f04..671ed22d5a 100644 --- a/plugins/UltimakerMachineActions/UpgradeFirmwareMachineAction.py +++ b/plugins/UltimakerMachineActions/UpgradeFirmwareMachineAction.py @@ -1,19 +1,58 @@ +# Copyright (c) 2018 Ultimaker B.V. +# Cura is released under the terms of the LGPLv3 or higher. + from UM.Application import Application from UM.Settings.DefinitionContainer import DefinitionContainer from cura.MachineAction import MachineAction from UM.i18n import i18nCatalog from UM.Settings.ContainerRegistry import ContainerRegistry +from PyQt5.QtCore import pyqtSignal, pyqtProperty, QObject +from typing import Optional + +MYPY = False +if MYPY: + from cura.PrinterOutput.FirmwareUpdater import FirmwareUpdater + catalog = i18nCatalog("cura") ## Upgrade the firmware of a machine by USB with this action. class UpgradeFirmwareMachineAction(MachineAction): - def __init__(self): + def __init__(self) -> None: super().__init__("UpgradeFirmware", catalog.i18nc("@action", "Upgrade Firmware")) self._qml_url = "UpgradeFirmwareMachineAction.qml" ContainerRegistry.getInstance().containerAdded.connect(self._onContainerAdded) - def _onContainerAdded(self, container): + self._active_output_device = None + + Application.getInstance().engineCreatedSignal.connect(self._onEngineCreated) + + def _onEngineCreated(self) -> None: + Application.getInstance().getMachineManager().outputDevicesChanged.connect(self._onOutputDevicesChanged) + + def _onContainerAdded(self, container) -> 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"): Application.getInstance().getMachineActionManager().addSupportedAction(container.getId(), self.getKey()) + + def _onOutputDevicesChanged(self) -> None: + if self._active_output_device: + self._active_output_device.activePrinter.getController().canUpdateFirmwareChanged.disconnect(self._onControllerCanUpdateFirmwareChanged) + output_devices = Application.getInstance().getMachineManager().printerOutputDevices + print(output_devices) + self._active_output_device = output_devices[0] if output_devices else None + if self._active_output_device: + 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.getController().can_update_firmware: + return self._active_output_device.getFirmwareUpdater() + + return None \ No newline at end of file diff --git a/plugins/UltimakerMachineActions/UpgradeFirmwareMachineAction.qml b/plugins/UltimakerMachineActions/UpgradeFirmwareMachineAction.qml index 1d0aabcae3..1c1f39edd0 100644 --- a/plugins/UltimakerMachineActions/UpgradeFirmwareMachineAction.qml +++ b/plugins/UltimakerMachineActions/UpgradeFirmwareMachineAction.qml @@ -1,4 +1,4 @@ -// Copyright (c) 2016 Ultimaker B.V. +// Copyright (c) 2018 Ultimaker B.V. // Cura is released under the terms of the LGPLv3 or higher. import QtQuick 2.2 @@ -59,7 +59,8 @@ Cura.MachineAction enabled: parent.firmwareName != "" && canUpdateFirmware onClicked: { - activeOutputDevice.updateFirmware(parent.firmwareName) + firmwareUpdateWindow.visible = true; + activeOutputDevice.updateFirmware(parent.firmwareName); } } Button @@ -78,7 +79,7 @@ Cura.MachineAction { width: parent.width wrapMode: Text.WordWrap - visible: !printerConnected + visible: !printerConnected && !firmwareUpdateWindow.visible text: catalog.i18nc("@label", "Firmware can not be upgraded because there is no connection with the printer."); } @@ -89,14 +90,102 @@ Cura.MachineAction visible: printerConnected && !canUpdateFirmware text: catalog.i18nc("@label", "Firmware can not be upgraded because the connection with the printer does not support upgrading firmware."); } + } - FileDialog + FileDialog + { + id: customFirmwareDialog + title: catalog.i18nc("@title:window", "Select custom firmware") + nameFilters: "Firmware image files (*.hex)" + selectExisting: true + onAccepted: { - id: customFirmwareDialog - title: catalog.i18nc("@title:window", "Select custom firmware") - nameFilters: "Firmware image files (*.hex)" - selectExisting: true - onAccepted: activeOutputDevice.updateFirmware(fileUrl) + firmwareUpdateWindow.visible = true; + activeOutputDevice.updateFirmware(fileUrl); } } + + UM.Dialog + { + id: firmwareUpdateWindow + + width: minimumWidth + minimumWidth: 500 * screenScaleFactor + height: minimumHeight + minimumHeight: 100 * screenScaleFactor + + modality: Qt.ApplicationModal + + title: catalog.i18nc("@title:window","Firmware Update") + + Column + { + anchors.fill: parent + + Label + { + anchors + { + left: parent.left + right: parent.right + } + + text: { + if(manager.firmwareUpdater == null) + { + return ""; + } + switch (manager.firmwareUpdater.firmwareUpdateState) + { + case 0: + return ""; //Not doing anything (eg; idling) + case 1: + return catalog.i18nc("@label","Updating firmware."); + case 2: + return catalog.i18nc("@label","Firmware update completed."); + case 3: + return catalog.i18nc("@label","Firmware update failed due to an unknown error."); + case 4: + return catalog.i18nc("@label","Firmware update failed due to an communication error."); + case 5: + return catalog.i18nc("@label","Firmware update failed due to an input/output error."); + case 6: + return catalog.i18nc("@label","Firmware update failed due to missing firmware."); + } + } + + wrapMode: Text.Wrap + } + + ProgressBar + { + id: prog + value: (manager.firmwareUpdater != null) ? manager.firmwareUpdater.firmwareProgress : 0 + minimumValue: 0 + maximumValue: 100 + indeterminate: + { + if(manager.firmwareUpdater == null) + { + return false; + } + return manager.firmwareUpdater.firmwareProgress < 1 && manager.firmwareUpdater.firmwareProgress > 0; + } + anchors + { + left: parent.left; + right: parent.right; + } + } + } + + rightButtons: [ + Button + { + text: catalog.i18nc("@action:button","Close"); + enabled: (manager.firmwareUpdater != null) ? manager.firmwareUpdater.firmwareUpdateState != 1 : true; + onClicked: firmwareUpdateWindow.visible = false; + } + ] + } } \ No newline at end of file diff --git a/resources/qml/FirmwareUpdateWindow.qml b/resources/qml/FirmwareUpdateWindow.qml deleted file mode 100644 index c71d70fc97..0000000000 --- a/resources/qml/FirmwareUpdateWindow.qml +++ /dev/null @@ -1,89 +0,0 @@ -// Copyright (c) 2017 Ultimaker B.V. -// Cura is released under the terms of the LGPLv3 or higher. - -import QtQuick 2.2 -import QtQuick.Window 2.2 -import QtQuick.Controls 1.2 - -import UM 1.1 as UM - -UM.Dialog -{ - id: base; - - width: minimumWidth; - minimumWidth: 500 * screenScaleFactor; - height: minimumHeight; - minimumHeight: 100 * screenScaleFactor; - - visible: true; - modality: Qt.ApplicationModal; - - title: catalog.i18nc("@title:window","Firmware Update"); - - Column - { - anchors.fill: parent; - - Label - { - anchors - { - left: parent.left; - right: parent.right; - } - - text: { - switch (manager.firmwareUpdateState) - { - case 0: - return "" //Not doing anything (eg; idling) - case 1: - return catalog.i18nc("@label","Updating firmware.") - case 2: - return catalog.i18nc("@label","Firmware update completed.") - case 3: - return catalog.i18nc("@label","Firmware update failed due to an unknown error.") - case 4: - return catalog.i18nc("@label","Firmware update failed due to an communication error.") - case 5: - return catalog.i18nc("@label","Firmware update failed due to an input/output error.") - case 6: - return catalog.i18nc("@label","Firmware update failed due to missing firmware.") - } - } - - wrapMode: Text.Wrap; - } - - ProgressBar - { - id: prog - value: manager.firmwareProgress - minimumValue: 0 - maximumValue: 100 - indeterminate: manager.firmwareProgress < 1 && manager.firmwareProgress > 0 - anchors - { - left: parent.left; - right: parent.right; - } - } - - SystemPalette - { - id: palette; - } - - UM.I18nCatalog { id: catalog; name: "cura"; } - } - - rightButtons: [ - Button - { - text: catalog.i18nc("@action:button","Close"); - enabled: manager.firmwareUpdateState != 1; - onClicked: base.visible = false; - } - ] -}