From 0655ef0bc52efa03b6892d417e79e3dbe26d638e Mon Sep 17 00:00:00 2001 From: Lipu Fei Date: Wed, 14 Mar 2018 14:22:19 +0100 Subject: [PATCH 1/4] Fix quality profile import CURA-4946 --- cura/Settings/CuraContainerRegistry.py | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/cura/Settings/CuraContainerRegistry.py b/cura/Settings/CuraContainerRegistry.py index 4e8ece0504..ebe8007955 100644 --- a/cura/Settings/CuraContainerRegistry.py +++ b/cura/Settings/CuraContainerRegistry.py @@ -204,7 +204,7 @@ class CuraContainerRegistry(ContainerRegistry): global_profile = profile_or_list[0] else: for profile in profile_or_list: - if not profile.getMetaDataEntry("extruder"): + if not profile.getMetaDataEntry("position"): global_profile = profile break if not global_profile: @@ -296,7 +296,7 @@ class CuraContainerRegistry(ContainerRegistry): else: #More extruders in the imported file than in the machine. continue #Delete the additional profiles. - result = self._configureProfile(profile, profile_id, new_name) + result = self._configureProfile(profile, profile_id, new_name, expected_machine_definition) if result is not None: return {"status": "error", "message": catalog.i18nc( "@info:status Don't translate the XML tags or !", @@ -324,7 +324,7 @@ class CuraContainerRegistry(ContainerRegistry): # \param new_name The new name for the profile. # # \return None if configuring was successful or an error message if an error occurred. - def _configureProfile(self, profile: InstanceContainer, id_seed: str, new_name: str) -> Optional[str]: + def _configureProfile(self, profile: InstanceContainer, id_seed: str, new_name: str, machine_definition_id: str) -> Optional[str]: profile.setDirty(True) # Ensure the profiles are correctly saved new_id = self.createUniqueName("quality_changes", "", id_seed, catalog.i18nc("@label", "Custom profile")) @@ -334,6 +334,7 @@ class CuraContainerRegistry(ContainerRegistry): # Set the unique Id to the profile, so it's generating a new one even if the user imports the same profile # It also solves an issue with importing profiles from G-Codes profile.setMetaDataEntry("id", new_id) + profile.setMetaDataEntry("definition", machine_definition_id) if "type" in profile.getMetaData(): profile.setMetaDataEntry("type", "quality_changes") From 877d061a1b19b16cda66c81989a6000c9b1018b5 Mon Sep 17 00:00:00 2001 From: Ghostkeeper Date: Wed, 14 Mar 2018 14:23:40 +0100 Subject: [PATCH 2/4] Catch FileNotFoundError when updating custom firmware In case there is a bug there, we won't crash the thread. --- plugins/USBPrinting/USBPrinterOutputDevice.py | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/plugins/USBPrinting/USBPrinterOutputDevice.py b/plugins/USBPrinting/USBPrinterOutputDevice.py index a17b2af3c3..14098b66f8 100644 --- a/plugins/USBPrinting/USBPrinterOutputDevice.py +++ b/plugins/USBPrinting/USBPrinterOutputDevice.py @@ -127,9 +127,11 @@ class USBPrinterOutputDevice(PrinterOutputDevice): if self._connection_state != ConnectionState.closed: self.close() - hex_file = intelHex.readHex(self._firmware_location) - if len(hex_file) == 0: - Logger.log("e", "Unable to read provided hex file. Could not update firmware") + try: + hex_file = intelHex.readHex(self._firmware_location) + assert len(hex_file) > 0 + except (FileNotFoundError, AssertionError): + Logger.log("e", "Unable to read provided hex file. Could not update firmware.") self.setFirmwareUpdateState(FirmwareUpdateState.firmware_not_found_error) return From 22573a685d5cd771202e950c2c0e2dc48da25fcc Mon Sep 17 00:00:00 2001 From: Lipu Fei Date: Wed, 14 Mar 2018 14:31:07 +0100 Subject: [PATCH 3/4] Fix quality definition comparison in quality importing CURA-4946 --- cura/Machines/QualityManager.py | 18 ++++++++++-------- cura/Settings/CuraContainerRegistry.py | 16 ++++++++++------ cura/Settings/MachineManager.py | 2 +- plugins/3MFReader/ThreeMFReader.py | 2 +- plugins/3MFReader/ThreeMFWorkspaceReader.py | 2 +- 5 files changed, 23 insertions(+), 17 deletions(-) diff --git a/cura/Machines/QualityManager.py b/cura/Machines/QualityManager.py index efb940b857..8d972c9192 100644 --- a/cura/Machines/QualityManager.py +++ b/cura/Machines/QualityManager.py @@ -16,6 +16,7 @@ from .QualityGroup import QualityGroup from .QualityNode import QualityNode if TYPE_CHECKING: + from UM.Settings.DefinitionContainer import DefinitionContainer from cura.Settings.GlobalStack import GlobalStack from .QualityChangesGroup import QualityChangesGroup @@ -178,7 +179,7 @@ class QualityManager(QObject): # Returns a dict of "custom profile name" -> QualityChangesGroup def getQualityChangesGroups(self, machine: "GlobalStack") -> dict: - machine_definition_id = getMachineDefinitionIDForQualitySearch(machine) + machine_definition_id = getMachineDefinitionIDForQualitySearch(machine.definition) machine_node = self._machine_quality_type_to_quality_changes_dict.get(machine_definition_id) if not machine_node: @@ -206,7 +207,7 @@ class QualityManager(QObject): # For more details, see QualityGroup. # def getQualityGroups(self, machine: "GlobalStack") -> dict: - machine_definition_id = getMachineDefinitionIDForQualitySearch(machine) + machine_definition_id = getMachineDefinitionIDForQualitySearch(machine.definition) # This determines if we should only get the global qualities for the global stack and skip the global qualities for the extruder stacks has_variant_materials = parseBool(machine.getMetaDataEntry("has_variant_materials", False)) @@ -315,7 +316,7 @@ class QualityManager(QObject): return quality_group_dict def getQualityGroupsForMachineDefinition(self, machine: "GlobalStack") -> dict: - machine_definition_id = getMachineDefinitionIDForQualitySearch(machine) + machine_definition_id = getMachineDefinitionIDForQualitySearch(machine.definition) # To find the quality container for the GlobalStack, check in the following fall-back manner: # (1) the machine-specific node @@ -460,7 +461,7 @@ class QualityManager(QObject): quality_changes.addMetaDataEntry("position", extruder_stack.getMetaDataEntry("position")) # If the machine specifies qualities should be filtered, ensure we match the current criteria. - machine_definition_id = getMachineDefinitionIDForQualitySearch(machine) + machine_definition_id = getMachineDefinitionIDForQualitySearch(machine.definition) quality_changes.setDefinition(machine_definition_id) quality_changes.addMetaDataEntry("setting_version", self._application.SettingVersion) @@ -480,12 +481,13 @@ class QualityManager(QObject): # Example: for an Ultimaker 3 Extended, it has "quality_definition = ultimaker3". This means Ultimaker 3 Extended # shares the same set of qualities profiles as Ultimaker 3. # -def getMachineDefinitionIDForQualitySearch(machine: "GlobalStack", default_definition_id: str = "fdmprinter") -> str: +def getMachineDefinitionIDForQualitySearch(machine_definition: "DefinitionContainer", + default_definition_id: str = "fdmprinter") -> str: machine_definition_id = default_definition_id - if parseBool(machine.getMetaDataEntry("has_machine_quality", False)): + if parseBool(machine_definition.getMetaDataEntry("has_machine_quality", False)): # Only use the machine's own quality definition ID if this machine has machine quality. - machine_definition_id = machine.getMetaDataEntry("quality_definition") + machine_definition_id = machine_definition.getMetaDataEntry("quality_definition") if machine_definition_id is None: - machine_definition_id = machine.definition.getId() + machine_definition_id = machine_definition.getId() return machine_definition_id diff --git a/cura/Settings/CuraContainerRegistry.py b/cura/Settings/CuraContainerRegistry.py index ebe8007955..0cf1c7399f 100644 --- a/cura/Settings/CuraContainerRegistry.py +++ b/cura/Settings/CuraContainerRegistry.py @@ -216,16 +216,21 @@ class CuraContainerRegistry(ContainerRegistry): # Make sure we have a profile_definition in the file: if profile_definition is None: break + machine_definition = self.findDefinitionContainers(id = profile_definition) + if not machine_definition: + Logger.log("e", "Incorrect profile [%s]. Unknown machine type [%s]", file_name, profile_definition) + return {"status": "error", + "message": catalog.i18nc("@info:status Don't translate the XML tags or !", "This profile {0} contains incorrect data, could not import it.", file_name) + } + machine_definition = machine_definition[0] # Get the expected machine definition. # i.e.: We expect gcode for a UM2 Extended to be defined as normal UM2 gcode... + profile_definition = getMachineDefinitionIDForQualitySearch(machine_definition) expected_machine_definition = getMachineDefinitionIDForQualitySearch(global_container_stack.definition) - # ...but that's not always the case for Cura 3.1 and older, so also get the current machine: - current_machine_definition = global_container_stack.definition.getId() - # And check if the profile_definition matches either one (showing error if not): - if profile_definition not in (expected_machine_definition, current_machine_definition): + if profile_definition != expected_machine_definition: Logger.log("e", "Profile [%s] is for machine [%s] but the current active machine is [%s]. Will not import the profile", file_name, profile_definition, expected_machine_definition) return { "status": "error", "message": catalog.i18nc("@info:status Don't translate the XML tags or !", "The machine defined in profile {0} ({1}) doesn't match with your current machine ({2}), could not import it.", file_name, profile_definition, expected_machine_definition)} @@ -345,9 +350,8 @@ class CuraContainerRegistry(ContainerRegistry): if not quality_type: return catalog.i18nc("@info:status", "Profile is missing a quality type.") - quality_type_criteria = {"quality_type": quality_type} global_stack = Application.getInstance().getGlobalContainerStack() - definition_id = getMachineDefinitionIDForQualitySearch(global_stack) + definition_id = getMachineDefinitionIDForQualitySearch(global_stack.definition) profile.setDefinition(definition_id) # Check to make sure the imported profile actually makes sense in context of the current configuration. diff --git a/cura/Settings/MachineManager.py b/cura/Settings/MachineManager.py index 019354ad40..3af6f70e5f 100755 --- a/cura/Settings/MachineManager.py +++ b/cura/Settings/MachineManager.py @@ -628,7 +628,7 @@ class MachineManager(QObject): @pyqtProperty(str, notify = globalContainerChanged) def activeQualityDefinitionId(self) -> str: if self._global_container_stack: - return getMachineDefinitionIDForQualitySearch(self._global_container_stack) + return getMachineDefinitionIDForQualitySearch(self._global_container_stack.definition) return "" ## Gets how the active definition calls variants diff --git a/plugins/3MFReader/ThreeMFReader.py b/plugins/3MFReader/ThreeMFReader.py index ec590a0212..3a1298bdba 100755 --- a/plugins/3MFReader/ThreeMFReader.py +++ b/plugins/3MFReader/ThreeMFReader.py @@ -122,7 +122,7 @@ class ThreeMFReader(MeshReader): um_node.callDecoration("setActiveExtruder", default_stack.getId()) # Get the definition & set it - definition_id = getMachineDefinitionIDForQualitySearch(global_container_stack) + definition_id = getMachineDefinitionIDForQualitySearch(global_container_stack.definition) um_node.callDecoration("getStack").getTop().setDefinition(definition_id) setting_container = um_node.callDecoration("getStack").getTop() diff --git a/plugins/3MFReader/ThreeMFWorkspaceReader.py b/plugins/3MFReader/ThreeMFWorkspaceReader.py index f20b9ab181..f5daa77bb0 100755 --- a/plugins/3MFReader/ThreeMFWorkspaceReader.py +++ b/plugins/3MFReader/ThreeMFWorkspaceReader.py @@ -719,7 +719,7 @@ class ThreeMFWorkspaceReader(WorkspaceReader): # Get the correct extruder definition IDs for quality changes from cura.Machines.QualityManager import getMachineDefinitionIDForQualitySearch - machine_definition_id_for_quality = getMachineDefinitionIDForQualitySearch(global_stack) + machine_definition_id_for_quality = getMachineDefinitionIDForQualitySearch(global_stack.definition) machine_definition_for_quality = self._container_registry.findDefinitionContainers(id = machine_definition_id_for_quality)[0] quality_changes_info = self._machine_info.quality_changes_info From 241611546e643ab50a2145b7186e6d3c5d4a2f1b Mon Sep 17 00:00:00 2001 From: Lipu Fei Date: Wed, 14 Mar 2018 14:41:43 +0100 Subject: [PATCH 4/4] Fix quality details view CURA-5054 --- cura/Machines/Models/QualitySettingsModel.py | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/cura/Machines/Models/QualitySettingsModel.py b/cura/Machines/Models/QualitySettingsModel.py index 4470ffc80e..b38f6f65c8 100644 --- a/cura/Machines/Models/QualitySettingsModel.py +++ b/cura/Machines/Models/QualitySettingsModel.py @@ -87,9 +87,11 @@ class QualitySettingsModel(ListModel): if self._selected_position == self.GLOBAL_STACK_POSITION: quality_node = quality_group.node_for_global else: - quality_node = quality_group.nodes_for_extruders.get(self._selected_position) + quality_node = quality_group.nodes_for_extruders.get(str(self._selected_position)) settings_keys = quality_group.getAllKeys() - quality_containers = [quality_node.getContainer()] + quality_containers = [] + if quality_node is not None: + quality_containers.append(quality_node.getContainer()) # Here, if the user has selected a quality changes, then "quality_changes_group" will not be None, and we fetch # the settings in that quality_changes_group. @@ -97,7 +99,7 @@ class QualitySettingsModel(ListModel): if self._selected_position == self.GLOBAL_STACK_POSITION: quality_changes_node = quality_changes_group.node_for_global else: - quality_changes_node = quality_changes_group.nodes_for_extruders.get(self._selected_position) + quality_changes_node = quality_changes_group.nodes_for_extruders.get(str(self._selected_position)) if quality_changes_node is not None: # it can be None if number of extruders are changed during runtime try: quality_containers.insert(0, quality_changes_node.getContainer())