diff --git a/cura/Settings/ContainerManager.py b/cura/Settings/ContainerManager.py index daf30d0792..94a79c9911 100644 --- a/cura/Settings/ContainerManager.py +++ b/cura/Settings/ContainerManager.py @@ -1,6 +1,7 @@ # Copyright (c) 2017 Ultimaker B.V. # Cura is released under the terms of the LGPLv3 or higher. +import copy import os.path import urllib import uuid @@ -751,27 +752,52 @@ class ContainerManager(QObject): # \return \type{str} the id of the newly created container. @pyqtSlot(str, result = str) def duplicateMaterial(self, material_id: str) -> str: - containers = self._container_registry.findInstanceContainers(id = material_id) - if not containers: + original = self._container_registry.findContainersMetadata(id = material_id) + if not original: Logger.log("d", "Unable to duplicate the material with id %s, because it doesn't exist.", material_id) return "" + original = original[0] + + base_container_id = original.get("base_file") + base_container = self._container_registry.findContainers(id = base_container_id) + if not base_container: + Logger.log("d", "Unable to duplicate the material with id {material_id}, because base_file {base_container_id} doesn't exist.".format(material_id = material_id, base_container_id = base_container_id)) + return "" + base_container = base_container[0] + + #We'll copy all containers with the same base. + #This way the correct variant and machine still gets assigned when loading the copy of the material. + containers_to_copy = self._container_registry.findInstanceContainers(base_file = base_container_id) # Ensure all settings are saved. Application.getInstance().saveSettings() # Create a new ID & container to hold the data. - new_id = self._container_registry.uniqueName(material_id) - container_type = type(containers[0]) # Could be either a XMLMaterialProfile or a InstanceContainer - duplicated_container = container_type(new_id) + new_containers = [] + new_base_id = self._container_registry.uniqueName(base_container.getId()) + new_base_container = copy.deepcopy(base_container) + new_base_container.getMetaData()["id"] = new_base_id + new_base_container.getMetaData()["base_file"] = new_base_id + new_containers.append(new_base_container) - # Instead of duplicating we load the data from the basefile again. - # This ensures that the inheritance goes well and all "cut up" subclasses of the xmlMaterial profile - # are also correctly created. - with open(containers[0].getPath(), encoding="utf-8") as f: - duplicated_container.deserialize(f.read()) - duplicated_container.setDirty(True) - self._container_registry.addContainer(duplicated_container) - return self._getMaterialContainerIdForActiveMachine(new_id) + #Clone all of them. + clone_of_original = None #Keeping track of which one is the clone of the original material, since we need to return that. + for container_to_copy in containers_to_copy: + #Create unique IDs for every clone. + current_id = container_to_copy.getId() + new_id = self._container_registry.uniqueName(current_id) + if current_id == material_id: + clone_of_original = new_id + + new_container = copy.deepcopy(container_to_copy) + new_container.getMetaData()["id"] = new_id + new_container.getMetaData()["base_file"] = new_base_id + new_containers.append(new_container) + + for container_to_add in new_containers: + container_to_add.setDirty(True) + ContainerRegistry.getInstance().addContainer(container_to_add) + return self._getMaterialContainerIdForActiveMachine(clone_of_original) ## Create a new material by cloning Generic PLA for the current material diameter and setting the GUID to something unqiue # @@ -839,7 +865,7 @@ class ContainerManager(QObject): if materials: return materials[0]["id"] - Logger.log("w", "Unable to find a suitable container based on %s for the current machine .", base_file) + Logger.log("w", "Unable to find a suitable container based on %s for the current machine.", base_file) return "" # do not activate a new material if a container can not be found return base_file