Create firmware update progress window from QML

This commit is contained in:
fieldOfView 2018-10-03 09:17:51 +02:00
parent b4e186ce78
commit 718ac0a307
5 changed files with 151 additions and 122 deletions

View file

@ -3,26 +3,25 @@
from PyQt5.QtCore import QObject, QUrl, pyqtSignal, pyqtProperty 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 enum import IntEnum
from threading import Thread from threading import Thread
from typing import Union from typing import Union
MYPY = False
if MYPY:
from cura.PrinterOutputDevice import PrinterOutputDevice
class FirmwareUpdater(QObject): class FirmwareUpdater(QObject):
firmwareProgressChanged = pyqtSignal() firmwareProgressChanged = pyqtSignal()
firmwareUpdateStateChanged = pyqtSignal() firmwareUpdateStateChanged = pyqtSignal()
def __init__(self, output_device: PrinterOutputDevice) -> None: def __init__(self, output_device: "PrinterOutputDevice") -> None:
super().__init__() super().__init__()
self._output_device = output_device self._output_device = output_device
self._update_firmware_thread = Thread(target=self._updateFirmware, daemon=True) self._update_firmware_thread = Thread(target=self._updateFirmware, daemon=True)
self._firmware_view = None
self._firmware_location = "" self._firmware_location = ""
self._firmware_progress = 0 self._firmware_progress = 0
self._firmware_update_state = FirmwareUpdateState.idle self._firmware_update_state = FirmwareUpdateState.idle
@ -33,7 +32,7 @@ class FirmwareUpdater(QObject):
self._firmware_location = QUrl(file).toLocalFile() self._firmware_location = QUrl(file).toLocalFile()
else: else:
self._firmware_location = file self._firmware_location = file
self._showFirmwareInterface()
self._setFirmwareUpdateState(FirmwareUpdateState.updating) self._setFirmwareUpdateState(FirmwareUpdateState.updating)
self._update_firmware_thread.start() self._update_firmware_thread.start()
@ -41,20 +40,6 @@ class FirmwareUpdater(QObject):
def _updateFirmware(self) -> None: def _updateFirmware(self) -> None:
raise NotImplementedError("_updateFirmware needs to be implemented") 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 ## Cleanup after a succesful update
def _cleanupAfterUpdate(self) -> None: def _cleanupAfterUpdate(self) -> None:
# Clean up for next attempt. # Clean up for next attempt.

View file

@ -20,6 +20,7 @@ MYPY = False
if MYPY: if MYPY:
from cura.PrinterOutput.PrinterOutputModel import PrinterOutputModel from cura.PrinterOutput.PrinterOutputModel import PrinterOutputModel
from cura.PrinterOutput.ConfigurationModel import ConfigurationModel from cura.PrinterOutput.ConfigurationModel import ConfigurationModel
from cura.PrinterOutput.FirmwareUpdater import FirmwareUpdater
i18n_catalog = i18nCatalog("cura") i18n_catalog = i18nCatalog("cura")
@ -83,6 +84,7 @@ class PrinterOutputDevice(QObject, OutputDevice):
self._connection_state = ConnectionState.closed #type: ConnectionState self._connection_state = ConnectionState.closed #type: ConnectionState
self._firmware_updater = None #type: Optional[FirmwareUpdater]
self._firmware_name = None #type: Optional[str] self._firmware_name = None #type: Optional[str]
self._address = "" #type: str self._address = "" #type: str
self._connection_text = "" #type: str self._connection_text = "" #type: str
@ -226,3 +228,6 @@ class PrinterOutputDevice(QObject, OutputDevice):
# This name can be used to define device type # This name can be used to define device type
def getFirmwareName(self) -> Optional[str]: def getFirmwareName(self) -> Optional[str]:
return self._firmware_name return self._firmware_name
def getFirmwareUpdater(self) -> Optional["FirmwareUpdater"]:
return self._firmware_updater

View file

@ -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.Application import Application
from UM.Settings.DefinitionContainer import DefinitionContainer from UM.Settings.DefinitionContainer import DefinitionContainer
from cura.MachineAction import MachineAction from cura.MachineAction import MachineAction
from UM.i18n import i18nCatalog from UM.i18n import i18nCatalog
from UM.Settings.ContainerRegistry import ContainerRegistry 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") catalog = i18nCatalog("cura")
## Upgrade the firmware of a machine by USB with this action. ## Upgrade the firmware of a machine by USB with this action.
class UpgradeFirmwareMachineAction(MachineAction): class UpgradeFirmwareMachineAction(MachineAction):
def __init__(self): def __init__(self) -> None:
super().__init__("UpgradeFirmware", catalog.i18nc("@action", "Upgrade Firmware")) super().__init__("UpgradeFirmware", catalog.i18nc("@action", "Upgrade Firmware"))
self._qml_url = "UpgradeFirmwareMachineAction.qml" self._qml_url = "UpgradeFirmwareMachineAction.qml"
ContainerRegistry.getInstance().containerAdded.connect(self._onContainerAdded) 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 # 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"): if isinstance(container, DefinitionContainer) and container.getMetaDataEntry("type") == "machine" and container.getMetaDataEntry("supports_usb_connection"):
Application.getInstance().getMachineActionManager().addSupportedAction(container.getId(), self.getKey()) 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

View file

@ -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. // Cura is released under the terms of the LGPLv3 or higher.
import QtQuick 2.2 import QtQuick 2.2
@ -59,7 +59,8 @@ Cura.MachineAction
enabled: parent.firmwareName != "" && canUpdateFirmware enabled: parent.firmwareName != "" && canUpdateFirmware
onClicked: onClicked:
{ {
activeOutputDevice.updateFirmware(parent.firmwareName) firmwareUpdateWindow.visible = true;
activeOutputDevice.updateFirmware(parent.firmwareName);
} }
} }
Button Button
@ -78,7 +79,7 @@ Cura.MachineAction
{ {
width: parent.width width: parent.width
wrapMode: Text.WordWrap 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."); 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 visible: printerConnected && !canUpdateFirmware
text: catalog.i18nc("@label", "Firmware can not be upgraded because the connection with the printer does not support upgrading firmware."); 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 firmwareUpdateWindow.visible = true;
title: catalog.i18nc("@title:window", "Select custom firmware") activeOutputDevice.updateFirmware(fileUrl);
nameFilters: "Firmware image files (*.hex)"
selectExisting: true
onAccepted: 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;
}
]
}
} }

View file

@ -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;
}
]
}