mirror of
https://github.com/Ultimaker/Cura.git
synced 2025-07-15 10:47:49 -06:00
WIP: Fix project loading
CURA-3756
This commit is contained in:
parent
19ee790cd7
commit
53141303d2
1 changed files with 131 additions and 30 deletions
|
@ -15,6 +15,8 @@ from .WorkspaceDialog import WorkspaceDialog
|
||||||
import xml.etree.ElementTree as ET
|
import xml.etree.ElementTree as ET
|
||||||
|
|
||||||
from cura.Settings.ExtruderManager import ExtruderManager
|
from cura.Settings.ExtruderManager import ExtruderManager
|
||||||
|
from cura.Settings.ExtruderStack import ExtruderStack
|
||||||
|
from cura.Settings.GlobalStack import GlobalStack
|
||||||
|
|
||||||
import zipfile
|
import zipfile
|
||||||
import io
|
import io
|
||||||
|
@ -35,6 +37,8 @@ class ThreeMFWorkspaceReader(WorkspaceReader):
|
||||||
self._material_container_suffix = None # We have to wait until all other plugins are loaded before we can set it
|
self._material_container_suffix = None # We have to wait until all other plugins are loaded before we can set it
|
||||||
self._instance_container_suffix = ContainerRegistry.getMimeTypeForContainer(InstanceContainer).preferredSuffix
|
self._instance_container_suffix = ContainerRegistry.getMimeTypeForContainer(InstanceContainer).preferredSuffix
|
||||||
self._container_stack_suffix = ContainerRegistry.getMimeTypeForContainer(ContainerStack).preferredSuffix
|
self._container_stack_suffix = ContainerRegistry.getMimeTypeForContainer(ContainerStack).preferredSuffix
|
||||||
|
self._extruder_stack_suffix = ContainerRegistry.getMimeTypeForContainer(ExtruderStack).preferredSuffix
|
||||||
|
self._global_stack_suffix = ContainerRegistry.getMimeTypeForContainer(GlobalStack).preferredSuffix
|
||||||
|
|
||||||
self._resolve_strategies = {}
|
self._resolve_strategies = {}
|
||||||
|
|
||||||
|
@ -47,6 +51,35 @@ class ThreeMFWorkspaceReader(WorkspaceReader):
|
||||||
self._id_mapping[old_id] = self._container_registry.uniqueName(old_id)
|
self._id_mapping[old_id] = self._container_registry.uniqueName(old_id)
|
||||||
return self._id_mapping[old_id]
|
return self._id_mapping[old_id]
|
||||||
|
|
||||||
|
## Separates the given file list into a list of GlobalStack files and a list of ExtruderStack files.
|
||||||
|
#
|
||||||
|
# In old versions, extruder stack files have the same suffix as container stack files ".stack.cfg".
|
||||||
|
#
|
||||||
|
def _determineGlobalAndExtruderStackFiles(self, project_file_name, file_list):
|
||||||
|
archive = zipfile.ZipFile(project_file_name, "r")
|
||||||
|
|
||||||
|
global_stack_file_list = [name for name in file_list if name.endswith(self._global_stack_suffix)]
|
||||||
|
extruder_stack_file_list = [name for name in file_list if name.endswith(self._extruder_stack_suffix)]
|
||||||
|
|
||||||
|
# separate container stack files and extruder stack files
|
||||||
|
files_to_determine = [name for name in file_list if name.endswith(self._container_stack_suffix)]
|
||||||
|
for file_name in files_to_determine:
|
||||||
|
container_id = self._stripFileToId(file_name)
|
||||||
|
stack = ContainerStack(container_id)
|
||||||
|
# Deserialize stack by converting read data from bytes to string
|
||||||
|
stack.deserialize(archive.open(file_name).read().decode("utf-8"), connect_signals=False)
|
||||||
|
|
||||||
|
stack_type = stack.getMetaDataEntry("type")
|
||||||
|
if stack_type == "extruder_train":
|
||||||
|
extruder_stack_file_list.append(file_name)
|
||||||
|
elif stack_type == "machine":
|
||||||
|
global_stack_file_list.append(file_name)
|
||||||
|
else:
|
||||||
|
Logger.log("w", "Unknown container stack type '%s' from %s in %s",
|
||||||
|
stack_type, file_name, project_file_name)
|
||||||
|
|
||||||
|
return global_stack_file_list, extruder_stack_file_list
|
||||||
|
|
||||||
def preRead(self, file_name, show_dialog=True, *args, **kwargs):
|
def preRead(self, file_name, show_dialog=True, *args, **kwargs):
|
||||||
self._3mf_mesh_reader = Application.getInstance().getMeshFileHandler().getReaderForFile(file_name)
|
self._3mf_mesh_reader = Application.getInstance().getMeshFileHandler().getReaderForFile(file_name)
|
||||||
if self._3mf_mesh_reader and self._3mf_mesh_reader.preRead(file_name) == WorkspaceReader.PreReadResult.accepted:
|
if self._3mf_mesh_reader and self._3mf_mesh_reader.preRead(file_name) == WorkspaceReader.PreReadResult.accepted:
|
||||||
|
@ -63,23 +96,13 @@ class ThreeMFWorkspaceReader(WorkspaceReader):
|
||||||
# Check if there are any conflicts, so we can ask the user.
|
# Check if there are any conflicts, so we can ask the user.
|
||||||
archive = zipfile.ZipFile(file_name, "r")
|
archive = zipfile.ZipFile(file_name, "r")
|
||||||
cura_file_names = [name for name in archive.namelist() if name.startswith("Cura/")]
|
cura_file_names = [name for name in archive.namelist() if name.startswith("Cura/")]
|
||||||
container_stack_files = [name for name in cura_file_names if name.endswith(self._container_stack_suffix)]
|
|
||||||
self._resolve_strategies = {"machine": None, "quality_changes": None, "material": None}
|
# A few lists of containers in this project files.
|
||||||
machine_conflict = False
|
# When loading the global stack file, it may be associated with those containers, which may or may not be
|
||||||
quality_changes_conflict = False
|
# in Cura already, so we need to provide them as alternative search lists.
|
||||||
for container_stack_file in container_stack_files:
|
definition_container_list = []
|
||||||
container_id = self._stripFileToId(container_stack_file)
|
instance_container_list = []
|
||||||
serialized = archive.open(container_stack_file).read().decode("utf-8")
|
material_container_list = []
|
||||||
if machine_name == "":
|
|
||||||
machine_name = self._getMachineNameFromSerializedStack(serialized)
|
|
||||||
stacks = self._container_registry.findContainerStacks(id=container_id)
|
|
||||||
if stacks:
|
|
||||||
# Check if there are any changes at all in any of the container stacks.
|
|
||||||
id_list = self._getContainerIdListFromSerialized(serialized)
|
|
||||||
for index, container_id in enumerate(id_list):
|
|
||||||
if stacks[0].getContainer(index).getId() != container_id:
|
|
||||||
machine_conflict = True
|
|
||||||
Job.yieldThread()
|
|
||||||
|
|
||||||
definition_container_files = [name for name in cura_file_names if name.endswith(self._definition_container_suffix)]
|
definition_container_files = [name for name in cura_file_names if name.endswith(self._definition_container_suffix)]
|
||||||
for definition_container_file in definition_container_files:
|
for definition_container_file in definition_container_files:
|
||||||
|
@ -93,6 +116,8 @@ class ThreeMFWorkspaceReader(WorkspaceReader):
|
||||||
else:
|
else:
|
||||||
definition_container = definitions[0]
|
definition_container = definitions[0]
|
||||||
|
|
||||||
|
definition_container_list.append(definition_container)
|
||||||
|
|
||||||
if definition_container.getMetaDataEntry("type") != "extruder":
|
if definition_container.getMetaDataEntry("type") != "extruder":
|
||||||
machine_type = definition_container.getName()
|
machine_type = definition_container.getName()
|
||||||
variant_type_name = definition_container.getMetaDataEntry("variants_name", variant_type_name)
|
variant_type_name = definition_container.getMetaDataEntry("variants_name", variant_type_name)
|
||||||
|
@ -131,6 +156,9 @@ class ThreeMFWorkspaceReader(WorkspaceReader):
|
||||||
|
|
||||||
# Deserialize InstanceContainer by converting read data from bytes to string
|
# Deserialize InstanceContainer by converting read data from bytes to string
|
||||||
instance_container.deserialize(archive.open(instance_container_file).read().decode("utf-8"))
|
instance_container.deserialize(archive.open(instance_container_file).read().decode("utf-8"))
|
||||||
|
|
||||||
|
instance_container_list.append(instance_container)
|
||||||
|
|
||||||
container_type = instance_container.getMetaDataEntry("type")
|
container_type = instance_container.getMetaDataEntry("type")
|
||||||
if container_type == "quality_changes":
|
if container_type == "quality_changes":
|
||||||
quality_name = instance_container.getName()
|
quality_name = instance_container.getName()
|
||||||
|
@ -151,6 +179,27 @@ class ThreeMFWorkspaceReader(WorkspaceReader):
|
||||||
num_user_settings += len(instance_container._instances)
|
num_user_settings += len(instance_container._instances)
|
||||||
|
|
||||||
Job.yieldThread()
|
Job.yieldThread()
|
||||||
|
|
||||||
|
# Determine ContainerStack files and ExtruderStack files
|
||||||
|
container_stack_files, extruder_stack_files = self._determineGlobalAndExtruderStackFiles(
|
||||||
|
file_name, cura_file_names)
|
||||||
|
self._resolve_strategies = {"machine": None, "quality_changes": None, "material": None}
|
||||||
|
machine_conflict = False
|
||||||
|
quality_changes_conflict = False
|
||||||
|
for container_stack_file in container_stack_files + extruder_stack_files:
|
||||||
|
container_id = self._stripFileToId(container_stack_file)
|
||||||
|
serialized = archive.open(container_stack_file).read().decode("utf-8")
|
||||||
|
if machine_name == "":
|
||||||
|
machine_name = self._getMachineNameFromSerializedStack(serialized)
|
||||||
|
stacks = self._container_registry.findContainerStacks(id=container_id)
|
||||||
|
if stacks:
|
||||||
|
# Check if there are any changes at all in any of the container stacks.
|
||||||
|
id_list = self._getContainerIdListFromSerialized(serialized)
|
||||||
|
for index, container_id in enumerate(id_list):
|
||||||
|
if stacks[0].getContainer(index).getId() != container_id:
|
||||||
|
machine_conflict = True
|
||||||
|
Job.yieldThread()
|
||||||
|
|
||||||
num_visible_settings = 0
|
num_visible_settings = 0
|
||||||
try:
|
try:
|
||||||
temp_preferences = Preferences()
|
temp_preferences = Preferences()
|
||||||
|
@ -336,10 +385,54 @@ class ThreeMFWorkspaceReader(WorkspaceReader):
|
||||||
|
|
||||||
# Get the stack(s) saved in the workspace.
|
# Get the stack(s) saved in the workspace.
|
||||||
Logger.log("d", "Workspace loading is checking stacks containers...")
|
Logger.log("d", "Workspace loading is checking stacks containers...")
|
||||||
container_stack_files = [name for name in cura_file_names if name.endswith(self._container_stack_suffix)]
|
container_stack_files, extruder_stack_files = self._determineGlobalAndExtruderStackFiles(file_name,
|
||||||
|
cura_file_names)
|
||||||
|
|
||||||
global_stack = None
|
global_stack = None
|
||||||
extruder_stacks = []
|
extruder_stacks = []
|
||||||
|
extruder_stacks_added = []
|
||||||
container_stacks_added = []
|
container_stacks_added = []
|
||||||
|
|
||||||
|
# load extruder stack files
|
||||||
|
try:
|
||||||
|
for extruder_stack_file in extruder_stack_files:
|
||||||
|
container_id = self._stripFileToId(extruder_stack_file)
|
||||||
|
|
||||||
|
container_stacks = self._container_registry.findContainerStacks(id=container_id)
|
||||||
|
if container_stacks:
|
||||||
|
# this container stack already exists, try to resolve
|
||||||
|
stack = container_stacks[0]
|
||||||
|
if self._resolve_strategies["machine"] == "override":
|
||||||
|
pass # do nothing
|
||||||
|
elif self._resolve_strategies["machine"] == "new":
|
||||||
|
# create a new extruder stack from this one
|
||||||
|
new_id = self.getNewId(container_id)
|
||||||
|
stack = ExtruderStack(new_id)
|
||||||
|
stack.deserialize(archive.open(extruder_stack_file).read().decode("utf-8"))
|
||||||
|
|
||||||
|
# Ensure a unique ID and name
|
||||||
|
stack._id = new_id
|
||||||
|
|
||||||
|
self._container_registry.addContainer(stack)
|
||||||
|
extruder_stacks_added.append(stack)
|
||||||
|
else:
|
||||||
|
# container not found, create a new one
|
||||||
|
stack = ExtruderStack(container_id)
|
||||||
|
stack.deserialize(archive.open(extruder_stack_file).read().decode("utf-8"))
|
||||||
|
self._container_registry.addContainer(stack)
|
||||||
|
extruder_stacks_added.append(stack)
|
||||||
|
|
||||||
|
extruder_stacks.append(stack)
|
||||||
|
|
||||||
|
except:
|
||||||
|
Logger.logException("w", "We failed to serialize the stack. Trying to clean up.")
|
||||||
|
# Something went really wrong. Try to remove any data that we added.
|
||||||
|
for container in extruder_stacks:
|
||||||
|
self._container_registry.removeContainer(container.getId())
|
||||||
|
|
||||||
|
return None
|
||||||
|
|
||||||
|
# load global stack file
|
||||||
try:
|
try:
|
||||||
for container_stack_file in container_stack_files:
|
for container_stack_file in container_stack_files:
|
||||||
container_id = self._stripFileToId(container_stack_file)
|
container_id = self._stripFileToId(container_stack_file)
|
||||||
|
@ -350,7 +443,7 @@ class ThreeMFWorkspaceReader(WorkspaceReader):
|
||||||
stack = container_stacks[0]
|
stack = container_stacks[0]
|
||||||
if self._resolve_strategies["machine"] == "override":
|
if self._resolve_strategies["machine"] == "override":
|
||||||
# TODO: HACK
|
# TODO: HACK
|
||||||
# There is a machine, check if it has authenticationd data. If so, keep that data.
|
# There is a machine, check if it has authentication data. If so, keep that data.
|
||||||
network_authentication_id = container_stacks[0].getMetaDataEntry("network_authentication_id")
|
network_authentication_id = container_stacks[0].getMetaDataEntry("network_authentication_id")
|
||||||
network_authentication_key = container_stacks[0].getMetaDataEntry("network_authentication_key")
|
network_authentication_key = container_stacks[0].getMetaDataEntry("network_authentication_key")
|
||||||
container_stacks[0].deserialize(archive.open(container_stack_file).read().decode("utf-8"))
|
container_stacks[0].deserialize(archive.open(container_stack_file).read().decode("utf-8"))
|
||||||
|
@ -360,7 +453,7 @@ class ThreeMFWorkspaceReader(WorkspaceReader):
|
||||||
container_stacks[0].addMetaDataEntry("network_authentication_key", network_authentication_key)
|
container_stacks[0].addMetaDataEntry("network_authentication_key", network_authentication_key)
|
||||||
elif self._resolve_strategies["machine"] == "new":
|
elif self._resolve_strategies["machine"] == "new":
|
||||||
new_id = self.getNewId(container_id)
|
new_id = self.getNewId(container_id)
|
||||||
stack = ContainerStack(new_id)
|
stack = GlobalStack(new_id)
|
||||||
stack.deserialize(archive.open(container_stack_file).read().decode("utf-8"))
|
stack.deserialize(archive.open(container_stack_file).read().decode("utf-8"))
|
||||||
|
|
||||||
# Ensure a unique ID and name
|
# Ensure a unique ID and name
|
||||||
|
@ -371,7 +464,6 @@ class ThreeMFWorkspaceReader(WorkspaceReader):
|
||||||
if stack.getMetaDataEntry("machine", None):
|
if stack.getMetaDataEntry("machine", None):
|
||||||
stack.setMetaDataEntry("machine", self.getNewId(stack.getMetaDataEntry("machine")))
|
stack.setMetaDataEntry("machine", self.getNewId(stack.getMetaDataEntry("machine")))
|
||||||
|
|
||||||
if stack.getMetaDataEntry("type") != "extruder_train":
|
|
||||||
# Only machines need a new name, stacks may be non-unique
|
# Only machines need a new name, stacks may be non-unique
|
||||||
stack.setName(self._container_registry.uniqueName(stack.getName()))
|
stack.setName(self._container_registry.uniqueName(stack.getName()))
|
||||||
container_stacks_added.append(stack)
|
container_stacks_added.append(stack)
|
||||||
|
@ -379,25 +471,26 @@ class ThreeMFWorkspaceReader(WorkspaceReader):
|
||||||
else:
|
else:
|
||||||
Logger.log("w", "Resolve strategy of %s for machine is not supported", self._resolve_strategies["machine"])
|
Logger.log("w", "Resolve strategy of %s for machine is not supported", self._resolve_strategies["machine"])
|
||||||
else:
|
else:
|
||||||
stack = ContainerStack(container_id)
|
# no existing container stack, so we create a new one
|
||||||
|
stack = GlobalStack(container_id)
|
||||||
# Deserialize stack by converting read data from bytes to string
|
# Deserialize stack by converting read data from bytes to string
|
||||||
stack.deserialize(archive.open(container_stack_file).read().decode("utf-8"))
|
stack.deserialize(archive.open(container_stack_file).read().decode("utf-8"))
|
||||||
container_stacks_added.append(stack)
|
container_stacks_added.append(stack)
|
||||||
self._container_registry.addContainer(stack)
|
self._container_registry.addContainer(stack)
|
||||||
|
|
||||||
if stack.getMetaDataEntry("type") == "extruder_train":
|
|
||||||
extruder_stacks.append(stack)
|
|
||||||
else:
|
|
||||||
global_stack = stack
|
global_stack = stack
|
||||||
Job.yieldThread()
|
Job.yieldThread()
|
||||||
except:
|
except:
|
||||||
Logger.logException("w", "We failed to serialize the stack. Trying to clean up.")
|
Logger.logException("w", "We failed to serialize the stack. Trying to clean up.")
|
||||||
# Something went really wrong. Try to remove any data that we added.
|
# Something went really wrong. Try to remove any data that we added.
|
||||||
for container in containers_to_add:
|
for container in containers_to_add:
|
||||||
self._container_registry.getInstance().removeContainer(container.getId())
|
self._container_registry.removeContainer(container.getId())
|
||||||
|
|
||||||
for container in container_stacks_added:
|
for container in container_stacks_added:
|
||||||
self._container_registry.getInstance().removeContainer(container.getId())
|
self._container_registry.removeContainer(container.getId())
|
||||||
|
|
||||||
|
for container in extruder_stacks_added:
|
||||||
|
self._container_registry.removeContainer(container.getId())
|
||||||
|
|
||||||
return None
|
return None
|
||||||
|
|
||||||
|
@ -466,6 +559,14 @@ class ThreeMFWorkspaceReader(WorkspaceReader):
|
||||||
# Notify everything/one that is to notify about changes.
|
# Notify everything/one that is to notify about changes.
|
||||||
global_stack.containersChanged.emit(global_stack.getTop())
|
global_stack.containersChanged.emit(global_stack.getTop())
|
||||||
|
|
||||||
|
# if we are reusing an existing global stack, it can already have extruders associated, so we need to remove
|
||||||
|
# them first
|
||||||
|
if global_stack.extruders:
|
||||||
|
old_extruder_stacks = global_stack.extruders
|
||||||
|
for extruder_stack in old_extruder_stacks:
|
||||||
|
self._container_registry.removeContainer(extruder_stack)
|
||||||
|
global_stack._extruders = []
|
||||||
|
|
||||||
for stack in extruder_stacks:
|
for stack in extruder_stacks:
|
||||||
stack.setNextStack(global_stack)
|
stack.setNextStack(global_stack)
|
||||||
stack.containersChanged.emit(stack.getTop())
|
stack.containersChanged.emit(stack.getTop())
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue