From 70c679859a9657f0488665324ea0dfef9a66bba1 Mon Sep 17 00:00:00 2001 From: ChrisTerBeke Date: Tue, 14 May 2019 20:56:28 +0200 Subject: [PATCH 1/9] Use default value for printer type, allow printer_type field from cloud --- plugins/UM3NetworkPrinting/src/Cloud/CloudOutputDevice.py | 5 +++-- .../src/Cloud/CloudOutputDeviceManager.py | 4 ++-- .../src/Cloud/Models/CloudClusterResponse.py | 6 +++++- 3 files changed, 10 insertions(+), 5 deletions(-) diff --git a/plugins/UM3NetworkPrinting/src/Cloud/CloudOutputDevice.py b/plugins/UM3NetworkPrinting/src/Cloud/CloudOutputDevice.py index 4f89513e1e..6a2186a87a 100644 --- a/plugins/UM3NetworkPrinting/src/Cloud/CloudOutputDevice.py +++ b/plugins/UM3NetworkPrinting/src/Cloud/CloudOutputDevice.py @@ -79,6 +79,7 @@ class CloudOutputDevice(NetworkedPrinterOutputDevice): b"address": cluster.host_internal_ip.encode() if cluster.host_internal_ip else b"", b"name": cluster.friendly_name.encode() if cluster.friendly_name else b"", b"firmware_version": cluster.host_version.encode() if cluster.host_version else b"", + b"printer_type": cluster.printer_type.encode() if cluster.printer_type else b"", b"cluster_size": b"1" # cloud devices are always clusters of at least one } @@ -104,7 +105,7 @@ class CloudOutputDevice(NetworkedPrinterOutputDevice): # We keep track of which printer is visible in the monitor page. self._active_printer = None # type: Optional[PrinterOutputModel] - self._host_machine_type = "" + self._host_machine_type = cluster.printer_type # type: str # Properties to populate later on with received cloud data. self._print_jobs = [] # type: List[UM3PrintJobOutputModel] @@ -375,7 +376,7 @@ class CloudOutputDevice(NetworkedPrinterOutputDevice): ## Gets the printer type of the cluster host. Falls back to the printer type in the device properties. @pyqtProperty(str, notify=_clusterPrintersChanged) def printerType(self) -> str: - if self._printers and self._host_machine_type in self._host_machine_variant_to_machine_type_map: + if self._host_machine_type in self._host_machine_variant_to_machine_type_map: return self._host_machine_variant_to_machine_type_map[self._host_machine_type] return super().printerType diff --git a/plugins/UM3NetworkPrinting/src/Cloud/CloudOutputDeviceManager.py b/plugins/UM3NetworkPrinting/src/Cloud/CloudOutputDeviceManager.py index 498e141b73..ced53e347b 100644 --- a/plugins/UM3NetworkPrinting/src/Cloud/CloudOutputDeviceManager.py +++ b/plugins/UM3NetworkPrinting/src/Cloud/CloudOutputDeviceManager.py @@ -96,7 +96,7 @@ class CloudOutputDeviceManager: device = CloudOutputDevice(self._api, cluster) self._remote_clusters[cluster.cluster_id] = device self._application.getDiscoveredPrintersModel().addDiscoveredPrinter( - cluster.cluster_id, + device.key, device.key, cluster.friendly_name, self._createMachineFromDiscoveredPrinter, @@ -109,7 +109,7 @@ class CloudOutputDeviceManager: for device, cluster in updates: device.clusterData = cluster self._application.getDiscoveredPrintersModel().updateDiscoveredPrinter( - cluster.cluster_id, + device.key, cluster.friendly_name, device.printerType, ) diff --git a/plugins/UM3NetworkPrinting/src/Cloud/Models/CloudClusterResponse.py b/plugins/UM3NetworkPrinting/src/Cloud/Models/CloudClusterResponse.py index 5549da02aa..a5b4dfdf40 100644 --- a/plugins/UM3NetworkPrinting/src/Cloud/Models/CloudClusterResponse.py +++ b/plugins/UM3NetworkPrinting/src/Cloud/Models/CloudClusterResponse.py @@ -15,9 +15,12 @@ class CloudClusterResponse(BaseCloudModel): # \param is_online: Whether this cluster is currently connected to the cloud. # \param status: The status of the cluster authentication (active or inactive). # \param host_version: The firmware version of the cluster host. This is where the Stardust client is running on. + # \param host_internal_ip: The internal IP address of the host printer. + # \param friendly_name: The human readable name of the host printer. + # \param printer_type: The machine type of the host printer. def __init__(self, cluster_id: str, host_guid: str, host_name: str, is_online: bool, status: str, host_internal_ip: Optional[str] = None, host_version: Optional[str] = None, - friendly_name: Optional[str] = None, **kwargs) -> None: + friendly_name: Optional[str] = None, printer_type: Optional[str] = "Ultimaker 3", **kwargs) -> None: self.cluster_id = cluster_id self.host_guid = host_guid self.host_name = host_name @@ -26,6 +29,7 @@ class CloudClusterResponse(BaseCloudModel): self.host_version = host_version self.host_internal_ip = host_internal_ip self.friendly_name = friendly_name + self.printer_type = printer_type super().__init__(**kwargs) # Validates the model, raising an exception if the model is invalid. From 56c1da2580f39207ceec0ecb36a2f37b9efd85f1 Mon Sep 17 00:00:00 2001 From: ChrisTerBeke Date: Tue, 14 May 2019 21:01:34 +0200 Subject: [PATCH 2/9] printer_type has a default value so cannot be Optional --- .../UM3NetworkPrinting/src/Cloud/Models/CloudClusterResponse.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/UM3NetworkPrinting/src/Cloud/Models/CloudClusterResponse.py b/plugins/UM3NetworkPrinting/src/Cloud/Models/CloudClusterResponse.py index a5b4dfdf40..8e8145a1bc 100644 --- a/plugins/UM3NetworkPrinting/src/Cloud/Models/CloudClusterResponse.py +++ b/plugins/UM3NetworkPrinting/src/Cloud/Models/CloudClusterResponse.py @@ -20,7 +20,7 @@ class CloudClusterResponse(BaseCloudModel): # \param printer_type: The machine type of the host printer. def __init__(self, cluster_id: str, host_guid: str, host_name: str, is_online: bool, status: str, host_internal_ip: Optional[str] = None, host_version: Optional[str] = None, - friendly_name: Optional[str] = None, printer_type: Optional[str] = "Ultimaker 3", **kwargs) -> None: + friendly_name: Optional[str] = None, printer_type: str = "Ultimaker 3", **kwargs) -> None: self.cluster_id = cluster_id self.host_guid = host_guid self.host_name = host_name From b1920b05e9e899bbe7f8c9d3e0d2e4d41b594c81 Mon Sep 17 00:00:00 2001 From: ChrisTerBeke Date: Tue, 14 May 2019 21:13:29 +0200 Subject: [PATCH 3/9] Remove hacky code that is now not needed anymore --- .../src/Cloud/CloudOutputDevice.py | 21 ------------------- .../src/Cloud/Models/CloudClusterResponse.py | 2 +- 2 files changed, 1 insertion(+), 22 deletions(-) diff --git a/plugins/UM3NetworkPrinting/src/Cloud/CloudOutputDevice.py b/plugins/UM3NetworkPrinting/src/Cloud/CloudOutputDevice.py index 6a2186a87a..df513f4174 100644 --- a/plugins/UM3NetworkPrinting/src/Cloud/CloudOutputDevice.py +++ b/plugins/UM3NetworkPrinting/src/Cloud/CloudOutputDevice.py @@ -58,14 +58,6 @@ class CloudOutputDevice(NetworkedPrinterOutputDevice): # Therefore we create a private signal used to trigger the printersChanged signal. _clusterPrintersChanged = pyqtSignal() - # Map of Cura Connect machine_variant field to Cura machine types. - # Needed for printer discovery stack creation. - _host_machine_variant_to_machine_type_map = { - "Ultimaker 3": "ultimaker3", - "Ultimaker 3 Extended": "ultimaker3_extended", - "Ultimaker S5": "ultimaker_s5" - } - ## Creates a new cloud output device # \param api_client: The client that will run the API calls # \param cluster: The device response received from the cloud API. @@ -105,7 +97,6 @@ class CloudOutputDevice(NetworkedPrinterOutputDevice): # We keep track of which printer is visible in the monitor page. self._active_printer = None # type: Optional[PrinterOutputModel] - self._host_machine_type = cluster.printer_type # type: str # Properties to populate later on with received cloud data. self._print_jobs = [] # type: List[UM3PrintJobOutputModel] @@ -245,11 +236,6 @@ class CloudOutputDevice(NetworkedPrinterOutputDevice): def _updatePrinters(self, printers: List[CloudClusterPrinterStatus]) -> None: previous = {p.key: p for p in self._printers} # type: Dict[str, PrinterOutputModel] received = {p.uuid: p for p in printers} # type: Dict[str, CloudClusterPrinterStatus] - - if len(printers) > 0: - # We need the machine type of the host (1st list entry) to allow discovery to work. - self._host_machine_type = printers[0].machine_variant - removed_printers, added_printers, updated_printers = findChanges(previous, received) for removed_printer in removed_printers: @@ -373,13 +359,6 @@ class CloudOutputDevice(NetworkedPrinterOutputDevice): ).show() self.writeFinished.emit() - ## Gets the printer type of the cluster host. Falls back to the printer type in the device properties. - @pyqtProperty(str, notify=_clusterPrintersChanged) - def printerType(self) -> str: - if self._host_machine_type in self._host_machine_variant_to_machine_type_map: - return self._host_machine_variant_to_machine_type_map[self._host_machine_type] - return super().printerType - ## Gets the number of printers in the cluster. # We use a minimum of 1 because cloud devices are always a cluster and printer discovery needs it. @pyqtProperty(int, notify = _clusterPrintersChanged) diff --git a/plugins/UM3NetworkPrinting/src/Cloud/Models/CloudClusterResponse.py b/plugins/UM3NetworkPrinting/src/Cloud/Models/CloudClusterResponse.py index 8e8145a1bc..89866ec603 100644 --- a/plugins/UM3NetworkPrinting/src/Cloud/Models/CloudClusterResponse.py +++ b/plugins/UM3NetworkPrinting/src/Cloud/Models/CloudClusterResponse.py @@ -17,7 +17,7 @@ class CloudClusterResponse(BaseCloudModel): # \param host_version: The firmware version of the cluster host. This is where the Stardust client is running on. # \param host_internal_ip: The internal IP address of the host printer. # \param friendly_name: The human readable name of the host printer. - # \param printer_type: The machine type of the host printer. + # \param printer_type: The machine type of the host printer, for example "Ultimaker 3". def __init__(self, cluster_id: str, host_guid: str, host_name: str, is_online: bool, status: str, host_internal_ip: Optional[str] = None, host_version: Optional[str] = None, friendly_name: Optional[str] = None, printer_type: str = "Ultimaker 3", **kwargs) -> None: From 913fac0094aca7f8a91e0534bb02e8037e1bbc0f Mon Sep 17 00:00:00 2001 From: ChrisTerBeke Date: Tue, 14 May 2019 21:18:00 +0200 Subject: [PATCH 4/9] Should be non-human readable string --- .../src/Cloud/Models/CloudClusterResponse.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/plugins/UM3NetworkPrinting/src/Cloud/Models/CloudClusterResponse.py b/plugins/UM3NetworkPrinting/src/Cloud/Models/CloudClusterResponse.py index 89866ec603..a872a6ba68 100644 --- a/plugins/UM3NetworkPrinting/src/Cloud/Models/CloudClusterResponse.py +++ b/plugins/UM3NetworkPrinting/src/Cloud/Models/CloudClusterResponse.py @@ -17,10 +17,10 @@ class CloudClusterResponse(BaseCloudModel): # \param host_version: The firmware version of the cluster host. This is where the Stardust client is running on. # \param host_internal_ip: The internal IP address of the host printer. # \param friendly_name: The human readable name of the host printer. - # \param printer_type: The machine type of the host printer, for example "Ultimaker 3". + # \param printer_type: The machine type of the host printer. def __init__(self, cluster_id: str, host_guid: str, host_name: str, is_online: bool, status: str, host_internal_ip: Optional[str] = None, host_version: Optional[str] = None, - friendly_name: Optional[str] = None, printer_type: str = "Ultimaker 3", **kwargs) -> None: + friendly_name: Optional[str] = None, printer_type: str = "ultimaker3", **kwargs) -> None: self.cluster_id = cluster_id self.host_guid = host_guid self.host_name = host_name From d4f891d5488d40a28b7ee1409588c7d53db05470 Mon Sep 17 00:00:00 2001 From: Remco Burema Date: Thu, 16 May 2019 12:39:12 +0200 Subject: [PATCH 5/9] Brim for prime tower fix for resolve. [CURA-6492] --- resources/definitions/fdmprinter.def.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/resources/definitions/fdmprinter.def.json b/resources/definitions/fdmprinter.def.json index 7453531a80..7cd9c42338 100644 --- a/resources/definitions/fdmprinter.def.json +++ b/resources/definitions/fdmprinter.def.json @@ -5352,7 +5352,7 @@ "description": "Prime-towers might need the extra adhesion afforded by a brim even if the model doesn't. Presently can't be used with the 'Raft' adhesion-type.", "type": "bool", "enabled": "resolveOrValue('prime_tower_enable') and (resolveOrValue('adhesion_type') != 'raft')", - "resolve": "resolveOrValue('prime_tower_enable') and (adhesion_type in ('none', 'skirt'))", + "resolve": "resolveOrValue('prime_tower_enable') and (resolveOrValue('adhesion_type') in ('none', 'skirt'))", "default_value": false, "settable_per_mesh": false, "settable_per_extruder": false From 1f6a8f2f7550cc0e5a5572003a89b6fd59360541 Mon Sep 17 00:00:00 2001 From: Ghostkeeper Date: Thu, 16 May 2019 14:27:43 +0200 Subject: [PATCH 6/9] Increment default API version number --- cura/ApplicationMetadata.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cura/ApplicationMetadata.py b/cura/ApplicationMetadata.py index faa3364e08..06fdd7a3f0 100644 --- a/cura/ApplicationMetadata.py +++ b/cura/ApplicationMetadata.py @@ -9,7 +9,7 @@ DEFAULT_CURA_DISPLAY_NAME = "Ultimaker Cura" DEFAULT_CURA_VERSION = "master" DEFAULT_CURA_BUILD_TYPE = "" DEFAULT_CURA_DEBUG_MODE = False -DEFAULT_CURA_SDK_VERSION = "6.0.0" +DEFAULT_CURA_SDK_VERSION = "6.1.0" try: from cura.CuraVersion import CuraAppName # type: ignore From 186eef0b68d1693219721f51789a1579f4599e0d Mon Sep 17 00:00:00 2001 From: Jaime van Kessel Date: Thu, 16 May 2019 15:38:44 +0200 Subject: [PATCH 7/9] Fix backup causing a crash in specific situations --- cura/Backups/BackupsManager.py | 14 ++++++++++++-- cura/CuraApplication.py | 4 ++-- 2 files changed, 14 insertions(+), 4 deletions(-) diff --git a/cura/Backups/BackupsManager.py b/cura/Backups/BackupsManager.py index 91ee578941..ba6fcab8d7 100644 --- a/cura/Backups/BackupsManager.py +++ b/cura/Backups/BackupsManager.py @@ -51,8 +51,18 @@ class BackupsManager: ## Here we try to disable the auto-save plug-in as it might interfere with # restoring a back-up. def _disableAutoSave(self) -> None: - self._application.getAutoSave().setEnabled(False) + auto_save = self._application.getAutoSave() + # The auto save is only not created if the application has not yet started. + if auto_save: + auto_save.setEnabled(False) + else: + Logger.log("e", "Unable to disable the autosave as application init has not been completed") ## Re-enable auto-save after we're done. def _enableAutoSave(self) -> None: - self._application.getAutoSave().setEnabled(True) + auto_save = self._application.getAutoSave() + # The auto save is only not created if the application has not yet started. + if auto_save: + auto_save.setEnabled(True) + else: + Logger.log("e", "Unable to enable the autosave as application init has not been completed") diff --git a/cura/CuraApplication.py b/cura/CuraApplication.py index 29febf2610..2f845c710f 100755 --- a/cura/CuraApplication.py +++ b/cura/CuraApplication.py @@ -260,7 +260,7 @@ class CuraApplication(QtApplication): self._plugins_loaded = False # Backups - self._auto_save = None + self._auto_save = None # type: Optional[AutoSave] from cura.Settings.CuraContainerRegistry import CuraContainerRegistry self._container_registry_class = CuraContainerRegistry @@ -988,7 +988,7 @@ class CuraApplication(QtApplication): return super().event(event) - def getAutoSave(self): + def getAutoSave(self) -> Optional[AutoSave]: return self._auto_save ## Get print information (duration / material used) From 915e0e2047e466c17ae6754c9da1ba2a01166990 Mon Sep 17 00:00:00 2001 From: Jaime van Kessel Date: Thu, 16 May 2019 15:41:52 +0200 Subject: [PATCH 8/9] Only add extrudernr to used extruders if it actually exists This can cause issues when a profile got messed up (especially when using profiles between different custom machines) --- cura/Settings/ExtruderManager.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/cura/Settings/ExtruderManager.py b/cura/Settings/ExtruderManager.py index 5ef308c779..3ed08cf118 100755 --- a/cura/Settings/ExtruderManager.py +++ b/cura/Settings/ExtruderManager.py @@ -279,7 +279,8 @@ class ExtruderManager(QObject): extruder_str_nr = str(global_stack.getProperty("adhesion_extruder_nr", "value")) if extruder_str_nr == "-1": extruder_str_nr = self._application.getMachineManager().defaultExtruderPosition - used_extruder_stack_ids.add(self.extruderIds[extruder_str_nr]) + if extruder_str_nr in self.extruderIds: + used_extruder_stack_ids.add(self.extruderIds[extruder_str_nr]) try: return [container_registry.findContainerStacks(id = stack_id)[0] for stack_id in used_extruder_stack_ids] From 1c9eab6b2bab3fce9fb3a0bd9efc47100bbdf87a Mon Sep 17 00:00:00 2001 From: Jaime van Kessel Date: Thu, 16 May 2019 15:48:09 +0200 Subject: [PATCH 9/9] Prevent crashes when backup fails to be restored Also add a bit of logging so that we know what / how it went wrong --- cura/Backups/Backup.py | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/cura/Backups/Backup.py b/cura/Backups/Backup.py index 399a4ea7b0..9ccdcaf64d 100644 --- a/cura/Backups/Backup.py +++ b/cura/Backups/Backup.py @@ -148,5 +148,9 @@ class Backup: Logger.log("d", "Removing current data in location: %s", target_path) Resources.factoryReset() Logger.log("d", "Extracting backup to location: %s", target_path) - archive.extractall(target_path) + try: + archive.extractall(target_path) + except PermissionError: + Logger.logException("e", "Unable to extract the backup due to permission errors") + return False return True