Rewrite cloning of materials

The original was based on reading the original file back, but that won't work if the files are provided by an arbitrary container provider. Instead we'll actually make a copy of all the profiles that need to be copied. It's much faster as well.

Contributes to issue CURA-4243.
This commit is contained in:
Ghostkeeper 2017-12-01 16:19:58 +01:00
parent 17ede12573
commit 083a4a8024
No known key found for this signature in database
GPG key ID: 5252B696FB5E7C7A

View file

@ -1,6 +1,7 @@
# Copyright (c) 2017 Ultimaker B.V. # Copyright (c) 2017 Ultimaker B.V.
# Cura is released under the terms of the LGPLv3 or higher. # Cura is released under the terms of the LGPLv3 or higher.
import copy
import os.path import os.path
import urllib import urllib
import uuid import uuid
@ -751,27 +752,52 @@ class ContainerManager(QObject):
# \return \type{str} the id of the newly created container. # \return \type{str} the id of the newly created container.
@pyqtSlot(str, result = str) @pyqtSlot(str, result = str)
def duplicateMaterial(self, material_id: str) -> str: def duplicateMaterial(self, material_id: str) -> str:
containers = self._container_registry.findInstanceContainers(id = material_id) original = self._container_registry.findContainersMetadata(id = material_id)
if not containers: if not original:
Logger.log("d", "Unable to duplicate the material with id %s, because it doesn't exist.", material_id) Logger.log("d", "Unable to duplicate the material with id %s, because it doesn't exist.", material_id)
return "" 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. # Ensure all settings are saved.
Application.getInstance().saveSettings() Application.getInstance().saveSettings()
# Create a new ID & container to hold the data. # Create a new ID & container to hold the data.
new_id = self._container_registry.uniqueName(material_id) new_containers = []
container_type = type(containers[0]) # Could be either a XMLMaterialProfile or a InstanceContainer new_base_id = self._container_registry.uniqueName(base_container.getId())
duplicated_container = container_type(new_id) 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. #Clone all of them.
# This ensures that the inheritance goes well and all "cut up" subclasses of the xmlMaterial profile clone_of_original = None #Keeping track of which one is the clone of the original material, since we need to return that.
# are also correctly created. for container_to_copy in containers_to_copy:
with open(containers[0].getPath(), encoding="utf-8") as f: #Create unique IDs for every clone.
duplicated_container.deserialize(f.read()) current_id = container_to_copy.getId()
duplicated_container.setDirty(True) new_id = self._container_registry.uniqueName(current_id)
self._container_registry.addContainer(duplicated_container) if current_id == material_id:
return self._getMaterialContainerIdForActiveMachine(new_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 ## Create a new material by cloning Generic PLA for the current material diameter and setting the GUID to something unqiue
# #