From 6d3fed8f52e4ef7e98fa9c894ea97a34002ac67e Mon Sep 17 00:00:00 2001 From: Ghostkeeper Date: Mon, 26 Mar 2018 15:48:03 +0200 Subject: [PATCH] Allow getContainer() to return None And in the rest of the locations we must then check if it's None and handle that gracefully. Here we assume that the getContainer message shows a message to the user if necessary. For now we'll just log it. Contributes to issue CURA-5045. --- cura/Machines/ContainerNode.py | 8 +++++--- cura/Machines/MaterialManager.py | 7 ++++++- cura/Machines/Models/QualitySettingsModel.py | 4 ++-- cura/Machines/QualityManager.py | 2 ++ cura/Settings/ContainerManager.py | 12 ++++++----- cura/Settings/CuraStackBuilder.py | 10 ++++++++-- cura/Settings/MachineManager.py | 20 ++++++++++++++----- plugins/3MFReader/ThreeMFWorkspaceReader.py | 6 +++--- .../XmlMaterialProfile/XmlMaterialProfile.py | 6 ++++-- 9 files changed, 52 insertions(+), 23 deletions(-) diff --git a/cura/Machines/ContainerNode.py b/cura/Machines/ContainerNode.py index 6a839fb921..125aaf56ad 100644 --- a/cura/Machines/ContainerNode.py +++ b/cura/Machines/ContainerNode.py @@ -30,9 +30,10 @@ class ContainerNode: def getChildNode(self, child_key: str) -> Optional["ContainerNode"]: return self.children_map.get(child_key) - def getContainer(self) -> "InstanceContainer": + def getContainer(self) -> Optional["InstanceContainer"]: if self.metadata is None: - raise RuntimeError("Cannot get container for a ContainerNode without metadata") + Logger.log("e", "Cannot get container for a ContainerNode without metadata.") + return None if self.container is None: container_id = self.metadata["id"] @@ -40,7 +41,8 @@ class ContainerNode: from UM.Settings.ContainerRegistry import ContainerRegistry container_list = ContainerRegistry.getInstance().findInstanceContainers(id = container_id) if not container_list: - raise RuntimeError("Failed to lazy-load container [%s], cannot find it" % container_id) + Logger.log("e", "Failed to lazy-load container [{container_id}]. Cannot find it.".format(container_id = container_id)) + return None self.container = container_list[0] return self.container diff --git a/cura/Machines/MaterialManager.py b/cura/Machines/MaterialManager.py index 24c7ccb8c0..5d78f589c6 100644 --- a/cura/Machines/MaterialManager.py +++ b/cura/Machines/MaterialManager.py @@ -423,7 +423,8 @@ class MaterialManager(QObject): return material_group = self.getMaterialGroup(root_material_id) - material_group.root_material_node.getContainer().setName(name) + if material_group: + material_group.root_material_node.getContainer().setName(name) # # Removes the given material. @@ -447,6 +448,8 @@ class MaterialManager(QObject): return None base_container = material_group.root_material_node.getContainer() + if not base_container: + return None # Ensure all settings are saved. self._application.saveSettings() @@ -466,6 +469,8 @@ class MaterialManager(QObject): # Clone all of them. for node in material_group.derived_material_node_list: container_to_copy = node.getContainer() + if not container_to_copy: + continue # Create unique IDs for every clone. new_id = new_base_id if container_to_copy.getMetaDataEntry("definition") != "fdmprinter": diff --git a/cura/Machines/Models/QualitySettingsModel.py b/cura/Machines/Models/QualitySettingsModel.py index b38f6f65c8..33eda2ec0d 100644 --- a/cura/Machines/Models/QualitySettingsModel.py +++ b/cura/Machines/Models/QualitySettingsModel.py @@ -90,7 +90,7 @@ class QualitySettingsModel(ListModel): quality_node = quality_group.nodes_for_extruders.get(str(self._selected_position)) settings_keys = quality_group.getAllKeys() quality_containers = [] - if quality_node is not None: + if quality_node is not None and quality_node.getContainer() 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 @@ -100,7 +100,7 @@ class QualitySettingsModel(ListModel): quality_changes_node = quality_changes_group.node_for_global else: 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 + if quality_changes_node is not None and quality_changes_node.getContainer() is not None: # it can be None if number of extruders are changed during runtime try: quality_containers.insert(0, quality_changes_node.getContainer()) except RuntimeError: diff --git a/cura/Machines/QualityManager.py b/cura/Machines/QualityManager.py index 8d972c9192..f6b8e6e36c 100644 --- a/cura/Machines/QualityManager.py +++ b/cura/Machines/QualityManager.py @@ -393,6 +393,8 @@ class QualityManager(QObject): new_name = self._container_registry.uniqueName(quality_changes_name) for node in quality_changes_group.getAllNodes(): container = node.getContainer() + if not container: + continue new_id = self._container_registry.uniqueName(container.getId()) self._container_registry.addContainer(container.duplicate(new_id, new_name)) diff --git a/cura/Settings/ContainerManager.py b/cura/Settings/ContainerManager.py index 760a288b7b..f0eb2303f2 100644 --- a/cura/Settings/ContainerManager.py +++ b/cura/Settings/ContainerManager.py @@ -98,9 +98,10 @@ class ContainerManager(QObject): entry_value = root container = material_group.root_material_node.getContainer() - container.setMetaDataEntry(entry_name, entry_value) - if sub_item_changed: #If it was only a sub-item that has changed then the setMetaDataEntry won't correctly notice that something changed, and we must manually signal that the metadata changed. - container.metaDataChanged.emit(container) + if container is not None: + container.setMetaDataEntry(entry_name, entry_value) + if sub_item_changed: #If it was only a sub-item that has changed then the setMetaDataEntry won't correctly notice that something changed, and we must manually signal that the metadata changed. + container.metaDataChanged.emit(container) ## Set a setting property of the specified container. # @@ -377,7 +378,8 @@ class ContainerManager(QObject): # NOTE: We only need to set the root material container because XmlMaterialProfile.setMetaDataEntry() will # take care of the derived containers too container = material_group.root_material_node.getContainer() - container.setMetaDataEntry("GUID", new_guid) + if container is not None: + container.setMetaDataEntry("GUID", new_guid) ## Get the singleton instance for this class. @classmethod @@ -466,5 +468,5 @@ class ContainerManager(QObject): if not path: return - container_list = [n.getContainer() for n in quality_changes_group.getAllNodes()] + container_list = [n.getContainer() for n in quality_changes_group.getAllNodes() if n.getContainer() is not None] self._container_registry.exportQualityProfile(container_list, path, file_type) diff --git a/cura/Settings/CuraStackBuilder.py b/cura/Settings/CuraStackBuilder.py index a8234b9de9..3c6ce59269 100644 --- a/cura/Settings/CuraStackBuilder.py +++ b/cura/Settings/CuraStackBuilder.py @@ -44,6 +44,8 @@ class CuraStackBuilder: global_variant_node = variant_manager.getDefaultVariantNode(machine_definition, VariantType.BUILD_PLATE) if global_variant_node: global_variant_container = global_variant_node.getContainer() + if not global_variant_container: + global_variant_container = application.empty_variant_container # get variant container for extruders extruder_variant_container = application.empty_variant_container @@ -51,6 +53,8 @@ class CuraStackBuilder: extruder_variant_name = None if extruder_variant_node: extruder_variant_container = extruder_variant_node.getContainer() + if not extruder_variant_container: + extruder_variant_container = application.empty_variant_container extruder_variant_name = extruder_variant_container.getName() generated_name = registry.createUniqueName("machine", "", name, machine_definition.getName()) @@ -72,7 +76,7 @@ class CuraStackBuilder: # get material container for extruders material_container = application.empty_material_container material_node = material_manager.getDefaultMaterial(new_global_stack, extruder_variant_name) - if material_node: + if material_node and material_node.getContainer(): material_container = material_node.getContainer() # Create ExtruderStacks @@ -107,8 +111,10 @@ class CuraStackBuilder: quality_group = quality_group_dict.get(preferred_quality_type) new_global_stack.quality = quality_group.node_for_global.getContainer() + if not new_global_stack.quality: + new_global_stack.quality = application.empty_quality_container for position, extruder_stack in new_global_stack.extruders.items(): - if position in quality_group.nodes_for_extruders: + if position in quality_group.nodes_for_extruders and quality_group.nodes_for_extruders[position].getContainer(): extruder_stack.quality = quality_group.nodes_for_extruders[position].getContainer() else: extruder_stack.quality = application.empty_quality_container diff --git a/cura/Settings/MachineManager.py b/cura/Settings/MachineManager.py index c25b58fbcf..6694bba0d6 100755 --- a/cura/Settings/MachineManager.py +++ b/cura/Settings/MachineManager.py @@ -987,6 +987,12 @@ class MachineManager(QObject): self.activeQualityChangesGroupChanged.emit() def _setQualityGroup(self, quality_group, empty_quality_changes = True): + if quality_group.node_for_global.getContainer() is None: + return + for node in quality_group.nodes_for_extruders.values(): + if node.getContainer() is None: + return + self._current_quality_group = quality_group if empty_quality_changes: self._current_quality_changes_group = None @@ -1012,9 +1018,9 @@ class MachineManager(QObject): quality_changes_container = self._empty_quality_changes_container quality_container = self._empty_quality_changes_container - if quality_changes_group.node_for_global: + if quality_changes_group.node_for_global and quality_changes_group.node_for_global.getContainer(): quality_changes_container = quality_changes_group.node_for_global.getContainer() - if quality_group.node_for_global: + if quality_group.node_for_global and quality_group.node_for_global.getContainer(): quality_container = quality_group.node_for_global.getContainer() self._global_container_stack.quality = quality_container @@ -1026,9 +1032,9 @@ class MachineManager(QObject): quality_changes_container = self._empty_quality_changes_container quality_container = self._empty_quality_container - if quality_changes_node: + if quality_changes_node and quality_changes_node.getContainer(): quality_changes_container = quality_changes_node.getContainer() - if quality_node: + if quality_node and quality_node.getContainer(): quality_container = quality_node.getContainer() extruder.quality = quality_container @@ -1040,14 +1046,18 @@ class MachineManager(QObject): self.activeQualityChangesGroupChanged.emit() def _setVariantNode(self, position, container_node): + if container_node.getContainer() is None: + return self._global_container_stack.extruders[position].variant = container_node.getContainer() self.activeVariantChanged.emit() def _setGlobalVariant(self, container_node): self._global_container_stack.variant = container_node.getContainer() + if not self._global_container_stack.variant: + self._global_container_stack.variant = Application.getInstance().empty_variant_container def _setMaterial(self, position, container_node = None): - if container_node: + if container_node and container_node.getContainer(): self._global_container_stack.extruders[position].material = container_node.getContainer() root_material_id = container_node.metadata["base_file"] else: diff --git a/plugins/3MFReader/ThreeMFWorkspaceReader.py b/plugins/3MFReader/ThreeMFWorkspaceReader.py index 633142187c..6a16c2905e 100755 --- a/plugins/3MFReader/ThreeMFWorkspaceReader.py +++ b/plugins/3MFReader/ThreeMFWorkspaceReader.py @@ -895,7 +895,7 @@ class ThreeMFWorkspaceReader(WorkspaceReader): variant_type = VariantType.BUILD_PLATE node = variant_manager.getVariantNode(global_stack.definition.getId(), variant_name, variant_type) - if node is not None: + if node is not None and node.getContainer() is not None: global_stack.variant = node.getContainer() for position, extruder_stack in extruder_stack_dict.items(): @@ -911,7 +911,7 @@ class ThreeMFWorkspaceReader(WorkspaceReader): variant_type = VariantType.NOZZLE node = variant_manager.getVariantNode(global_stack.definition.getId(), variant_name, variant_type) - if node is not None: + if node is not None and node.getContainer() is not None: extruder_stack.variant = node.getContainer() def _applyMaterials(self, global_stack, extruder_stack_dict): @@ -937,7 +937,7 @@ class ThreeMFWorkspaceReader(WorkspaceReader): extruder_stack.variant.getName(), machine_material_diameter, root_material_id) - if material_node is not None: + if material_node is not None and material_node.getContainer() is not None: extruder_stack.material = material_node.getContainer() def _applyChangesToMachine(self, global_stack, extruder_stack_dict): diff --git a/plugins/XmlMaterialProfile/XmlMaterialProfile.py b/plugins/XmlMaterialProfile/XmlMaterialProfile.py index 54caca855e..6dcd5a5ccc 100644 --- a/plugins/XmlMaterialProfile/XmlMaterialProfile.py +++ b/plugins/XmlMaterialProfile/XmlMaterialProfile.py @@ -71,12 +71,14 @@ class XmlMaterialProfile(InstanceContainer): # Update the root material container root_material_container = material_group.root_material_node.getContainer() - root_material_container.setMetaDataEntry(key, value, apply_to_all = False) + if root_material_container is not None: + root_material_container.setMetaDataEntry(key, value, apply_to_all = False) # Update all containers derived from it for node in material_group.derived_material_node_list: container = node.getContainer() - container.setMetaDataEntry(key, value, apply_to_all = False) + if container is not None: + container.setMetaDataEntry(key, value, apply_to_all = False) ## Overridden from InstanceContainer, similar to setMetaDataEntry. # without this function the setName would only set the name of the specific nozzle / material / machine combination container