def _materialRemoved(self, container: ContainerInterface) -> None: if container.getMetaDataEntry("type") != "material": return # Only interested in materials. base_file = container.getMetaDataEntry("base_file") if base_file not in self.materials: return # We don't track this material anyway. No need to remove it. original_node = self.materials[base_file] del self.materials[base_file] self.materialsChanged.emit(original_node) # Now a different material from the same base file may have been hidden because it was not as specific as the one we deleted. # Search for any submaterials from that base file that are still left. materials_same_base_file = ContainerRegistry.getInstance().findContainersMetadata(base_file = base_file) if materials_same_base_file: most_specific_submaterial = None for submaterial in materials_same_base_file: if submaterial["definition"] == self.machine.container_id: if submaterial.get("variant_name", "empty") == self.variant_name: most_specific_submaterial = submaterial break # most specific match possible if submaterial.get("variant_name", "empty") == "empty": most_specific_submaterial = submaterial if most_specific_submaterial is None: Logger.log("w", "Material %s removed, but no suitable replacement found", base_file) else: Logger.log("i", "Material %s (%s) overridden by %s", base_file, self.variant_name, most_specific_submaterial.get("id")) self.materials[base_file] = MaterialNode(most_specific_submaterial["id"], variant = self) self.materialsChanged.emit(self.materials[base_file]) if not self.materials: # The last available material just got deleted and there is nothing with the same base file to replace it. self.materials["empty_material"] = MaterialNode("empty_material", variant = self) self.materialsChanged.emit(self.materials["empty_material"])
def replaceContainer(self, index: int, container: ContainerInterface, postpone_emit: bool = False) -> None: """Overridden from ContainerStack Replaces the container at the specified index with another container. This version performs checks to make sure the new container has the expected metadata and type. :throws Exception.InvalidContainerError Raised when trying to replace a container with a container that has an incorrect type. """ expected_type = _ContainerIndexes.IndexTypeMap[index] if expected_type == "definition": if not isinstance(container, DefinitionContainer): raise Exceptions.InvalidContainerError( "Cannot replace container at index {index} with a container that is not a DefinitionContainer" .format(index=index)) elif container != self._empty_instance_container and container.getMetaDataEntry( "type") != expected_type: raise Exceptions.InvalidContainerError( "Cannot replace container at index {index} with a container that is not of {type} type, but {actual_type} type." .format(index=index, type=expected_type, actual_type=container.getMetaDataEntry("type"))) current_container = self._containers[index] if current_container.getId() == container.getId(): return super().replaceContainer(index, container, postpone_emit)
def _onContainerAdded(self, container: ContainerInterface) -> None: # We don't have all the machines loaded in the beginning, so in order to add the missing extruder stack # for single extrusion machines, we subscribe to the containerAdded signal, and whenever a global stack # is added, we check to see if an extruder stack needs to be added. if not isinstance(container, ContainerStack) or container.getMetaDataEntry("type") != "machine": return machine_extruder_trains = container.getMetaDataEntry("machine_extruder_trains") if machine_extruder_trains is not None and machine_extruder_trains != {"0": "fdmextruder"}: return extruder_stacks = self.findContainerStacks(type = "extruder_train", machine = container.getId()) if not extruder_stacks: self.addExtruderStackForSingleExtrusionMachine(container, "fdmextruder")
def replaceContainer(self, index: int, container: ContainerInterface, postpone_emit: bool = False) -> None: expected_type = _ContainerIndexes.IndexTypeMap[index] if expected_type == "definition": if not isinstance(container, DefinitionContainer): raise Exceptions.InvalidContainerError("Cannot replace container at index {index} with a container that is not a DefinitionContainer".format(index = index)) elif container != self._empty_instance_container and container.getMetaDataEntry("type") != expected_type: raise Exceptions.InvalidContainerError("Cannot replace container at index {index} with a container that is not of {type} type, but {actual_type} type.".format(index = index, type = expected_type, actual_type = container.getMetaDataEntry("type"))) super().replaceContainer(index, container, postpone_emit)
def _on_printer_container_removed(self, container: ContainerInterface) -> None: """Removes device if it is managed by this plugin. Called when the user deletes a printer. Args: container: deleted container. """ device_id = container.getMetaDataEntry(_METADATA_MPSM2_KEY) self.remove_device(device_id, _get_address(device_id))
def _printerRemoved(self, container: ContainerInterface) -> None: """ Callback connected to the containerRemoved signal. Invoked when a cloud printer is removed from Cura to remove the printer's reference from the _remote_clusters. :param container: The ContainerInterface passed to this function whenever the ContainerRemoved signal is emitted :return: None """ if isinstance(container, GlobalStack): container_cluster_id = container.getMetaDataEntry(self.META_CLUSTER_ID, None) if container_cluster_id in self._remote_clusters.keys(): del self._remote_clusters[container_cluster_id]
def _materialAdded(self, container: ContainerInterface) -> None: if container.getMetaDataEntry("type") != "material": return # Not interested. if not self.machine.has_materials: return # We won't add any materials. material_definition = container.getMetaDataEntry("definition") base_file = container.getMetaDataEntry("base_file") if base_file in self.machine.exclude_materials: return # Material is forbidden for this printer. if base_file not in self.materials: # Completely new base file. Always better than not having a file as long as it matches our set-up. if material_definition != "fdmprinter" and material_definition != self.machine.container_id: return material_variant = container.getMetaDataEntry("variant_name", "empty") if material_variant != "empty" and material_variant != self.variant_name: return else: # We already have this base profile. Replace the base profile if the new one is more specific. new_definition = container.getMetaDataEntry("definition") if new_definition == "fdmprinter": return # Just as unspecific or worse. if new_definition != self.machine.container_id: return # Doesn't match this set-up. original_metadata = ContainerRegistry.getInstance().findContainersMetadata(id = self.materials[base_file].container_id)[0] original_variant = original_metadata.get("variant_name", "empty") if original_variant != "empty" or container.getMetaDataEntry("variant_name", "empty") == "empty": return # Original was already specific or just as unspecific as the new one. if "empty_material" in self.materials: del self.materials["empty_material"] self.materials[base_file] = MaterialNode(container.getId(), variant = self) self.materials[base_file].materialChanged.connect(self.materialsChanged) self.materialsChanged.emit(self.materials[base_file])
def addContainer(self, container: ContainerInterface) -> None: # Note: Intentional check with type() because we want to ignore subclasses if type(container) == ContainerStack: container = self._convertContainerStack(cast(ContainerStack, container)) if isinstance(container, InstanceContainer) and type(container) != type(self.getEmptyInstanceContainer()): # Check against setting version of the definition. required_setting_version = cura.CuraApplication.CuraApplication.SettingVersion actual_setting_version = int(container.getMetaDataEntry("setting_version", default = 0)) if required_setting_version != actual_setting_version: Logger.log("w", "Instance container {container_id} is outdated. Its setting version is {actual_setting_version} but it should be {required_setting_version}.".format(container_id = container.getId(), actual_setting_version = actual_setting_version, required_setting_version = required_setting_version)) return # Don't add. super().addContainer(container)
def setProperty(self, name: str, value: Any, container: ContainerInterface = None): if SettingDefinition.hasProperty(name): if SettingDefinition.isReadOnlyProperty(name): Logger.log( "e", "Tried to set property %s which is a read-only property", name) return if name not in self.__property_values or value != self.__property_values[ name]: if isinstance(value, str) and value.strip().startswith("="): value = SettingFunction.SettingFunction(value[1:]) self.__property_values[name] = value if name == "value": if not container: container = self._container ## If state changed, emit the signal if self._state != InstanceState.User and container.getMetaDataEntry( "type") == "user": self._state = InstanceState.User self.propertyChanged.emit(self._definition.key, "state") self.updateRelations(container) if self._validator: self.propertyChanged.emit(self._definition.key, "validationState") self.propertyChanged.emit(self._definition.key, name) for property_name in self._definition.getPropertyNames(): if self._definition.dependsOnProperty( property_name) == name: self.propertyChanged.emit(self._definition.key, property_name) else: if name == "state": if value == "InstanceState.Calculated": if self._state != InstanceState.Calculated: self._state = InstanceState.Calculated self.propertyChanged.emit(self._definition.key, "state") else: raise AttributeError("No property {0} defined".format(name))
def _materialAdded(self, container: ContainerInterface) -> None: if container.getMetaDataEntry("type") != "material": return # Not interested. if not ContainerRegistry.getInstance().findContainersMetadata( id=container.getId()): # CURA-6889 # containerAdded and removed signals may be triggered in the next event cycle. If a container gets added # and removed in the same event cycle, in the next cycle, the connections should just ignore the signals. # The check here makes sure that the container in the signal still exists. Logger.log( "d", "Got container added signal for container [%s] but it no longer exists, do nothing.", container.getId()) return if not self.machine.has_materials: return # We won't add any materials. material_definition = container.getMetaDataEntry("definition") base_file = container.getMetaDataEntry("base_file") if base_file in self.machine.exclude_materials: return # Material is forbidden for this printer. if base_file not in self.materials: # Completely new base file. Always better than not having a file as long as it matches our set-up. if material_definition != "fdmprinter" and material_definition != self.machine.container_id: return material_variant = container.getMetaDataEntry("variant_name") if material_variant is not None and material_variant != self.variant_name: return else: # We already have this base profile. Replace the base profile if the new one is more specific. new_definition = container.getMetaDataEntry("definition") if new_definition == "fdmprinter": return # Just as unspecific or worse. material_variant = container.getMetaDataEntry("variant_name") if new_definition != self.machine.container_id or material_variant != self.variant_name: return # Doesn't match this set-up. original_metadata = ContainerRegistry.getInstance( ).findContainersMetadata( id=self.materials[base_file].container_id)[0] if "variant_name" in original_metadata or material_variant is None: return # Original was already specific or just as unspecific as the new one. if "empty_material" in self.materials: del self.materials["empty_material"] self.materials[base_file] = MaterialNode(container.getId(), variant=self) self.materials[base_file].materialChanged.connect( self.materialsChanged) self.materialsChanged.emit(self.materials[base_file])