From 316f2bbdb517a565f55ffe3b02b13e5aee21ac79 Mon Sep 17 00:00:00 2001 From: Jaime van Kessel Date: Wed, 10 May 2017 09:49:33 +0200 Subject: [PATCH 1/6] Fixed switching g-code flavors with machineAction --- plugins/MachineSettingsAction/MachineSettingsAction.py | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/plugins/MachineSettingsAction/MachineSettingsAction.py b/plugins/MachineSettingsAction/MachineSettingsAction.py index 486ab25918..bfade90f2b 100755 --- a/plugins/MachineSettingsAction/MachineSettingsAction.py +++ b/plugins/MachineSettingsAction/MachineSettingsAction.py @@ -251,7 +251,7 @@ class MachineSettingsAction(MachineAction): if definition.getProperty("machine_gcode_flavor", "value") == "UltiGCode" and not definition.getMetaDataEntry("has_materials", False): has_materials = self._global_container_stack.getProperty("machine_gcode_flavor", "value") != "UltiGCode" - material_container = self._global_container_stack.findContainer({"type": "material"}) + material_container = self._global_container_stack.material material_index = self._global_container_stack.getContainerIndex(material_container) if has_materials: @@ -272,7 +272,6 @@ class MachineSettingsAction(MachineAction): if "has_materials" in self._global_container_stack.getMetaData(): self._global_container_stack.removeMetaDataEntry("has_materials") - empty_material = self._container_registry.findInstanceContainers(id = "empty_material")[0] - self._global_container_stack.replaceContainer(material_index, empty_material) + self._global_container_stack.material = ContainerRegistry.getInstance().getEmptyInstanceContainer() Application.getInstance().globalContainerStackChanged.emit() From 3d429e44aeb5e00cb6d5ded36104de322bd9ec9c Mon Sep 17 00:00:00 2001 From: Jaime van Kessel Date: Wed, 10 May 2017 09:59:19 +0200 Subject: [PATCH 2/6] Updating extruders now also works with timer CURA-3780 --- cura/Settings/ExtrudersModel.py | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/cura/Settings/ExtrudersModel.py b/cura/Settings/ExtrudersModel.py index 74680bb293..e742ba4bd8 100644 --- a/cura/Settings/ExtrudersModel.py +++ b/cura/Settings/ExtrudersModel.py @@ -1,7 +1,7 @@ # Copyright (c) 2016 Ultimaker B.V. # Cura is released under the terms of the AGPLv3 or higher. -from PyQt5.QtCore import Qt, pyqtSignal, pyqtProperty, pyqtSlot +from PyQt5.QtCore import Qt, pyqtSignal, pyqtProperty, QTimer import UM.Qt.ListModel from UM.Application import Application @@ -58,6 +58,11 @@ class ExtrudersModel(UM.Qt.ListModel.ListModel): self.addRoleName(self.MaterialRole, "material") self.addRoleName(self.VariantRole, "variant") + self._update_extruder_timer = QTimer() + self._update_extruder_timer.setInterval(250) + self._update_extruder_timer.setSingleShot(True) + self._update_extruder_timer.timeout.connect(self.__updateExtruders) + self._add_global = False self._simple_names = False @@ -118,10 +123,13 @@ class ExtrudersModel(UM.Qt.ListModel.ListModel): modelChanged = pyqtSignal() + def _updateExtruders(self): + self._update_extruder_timer.start() + ## Update the list of extruders. # # This should be called whenever the list of extruders changes. - def _updateExtruders(self): + def __updateExtruders(self): changed = False if self.rowCount() != 0: From 9a387f9ee2beb705afe959df92d405fc81720ccf Mon Sep 17 00:00:00 2001 From: Jaime van Kessel Date: Wed, 10 May 2017 10:33:40 +0200 Subject: [PATCH 3/6] ReplaceQuality changes only emits signals if there was a change CURA-3780 --- cura/Settings/MachineManager.py | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/cura/Settings/MachineManager.py b/cura/Settings/MachineManager.py index 7e7ad07ff0..2207ee65dd 100755 --- a/cura/Settings/MachineManager.py +++ b/cura/Settings/MachineManager.py @@ -810,13 +810,13 @@ class MachineManager(QObject): # Quality profile come in two flavours: type=quality and type=quality_changes # If we found a quality_changes profile then look up its parent quality profile. container_type = containers[0].getMetaDataEntry("type") - quality_name = containers[0].getName() - quality_type = containers[0].getMetaDataEntry("quality_type") # Get quality container and optionally the quality_changes container. if container_type == "quality": + quality_type = containers[0].getMetaDataEntry("quality_type") new_quality_settings_list = self.determineQualityAndQualityChangesForQualityType(quality_type) elif container_type == "quality_changes": + quality_name = containers[0].getName() new_quality_settings_list = self._determineQualityAndQualityChangesForQualityChanges(quality_name) else: Logger.log("e", "Tried to set quality to a container that is not of the right type") @@ -952,12 +952,16 @@ class MachineManager(QObject): # Disconnect the signal handling from the old container. container_type = container.getMetaDataEntry("type") if container_type == "quality": + if stack.quality == container: + return # Nothing to do stack.quality.nameChanged.disconnect(self._onQualityNameChanged) stack.setQuality(container) stack.qualityChanges.nameChanged.connect(self._onQualityNameChanged) elif container_type == "quality_changes" or container_type is None: # If the container is an empty container, we need to change the quality_changes. # Quality can never be set to empty. + if stack.qualityChanges == container: + return # Nothing to do stack.qualityChanges.nameChanged.disconnect(self._onQualityNameChanged) stack.setQualityChanges(container) stack.qualityChanges.nameChanged.connect(self._onQualityNameChanged) From 42fc703516b97cc4508a19f67b2e0154c091a3e8 Mon Sep 17 00:00:00 2001 From: Jaime van Kessel Date: Wed, 10 May 2017 10:45:07 +0200 Subject: [PATCH 4/6] Added a few profiling decorators to expensive methods --- cura/Settings/ExtrudersModel.py | 3 ++- cura/Settings/MachineManager.py | 2 ++ 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/cura/Settings/ExtrudersModel.py b/cura/Settings/ExtrudersModel.py index e742ba4bd8..54bf0df3b6 100644 --- a/cura/Settings/ExtrudersModel.py +++ b/cura/Settings/ExtrudersModel.py @@ -5,7 +5,7 @@ from PyQt5.QtCore import Qt, pyqtSignal, pyqtProperty, QTimer import UM.Qt.ListModel from UM.Application import Application - +import UM.FlameProfiler from cura.Settings.ExtruderManager import ExtruderManager ## Model that holds extruders. @@ -129,6 +129,7 @@ class ExtrudersModel(UM.Qt.ListModel.ListModel): ## Update the list of extruders. # # This should be called whenever the list of extruders changes. + @UM.FlameProfiler.profile def __updateExtruders(self): changed = False diff --git a/cura/Settings/MachineManager.py b/cura/Settings/MachineManager.py index 2207ee65dd..80e37fc7c5 100755 --- a/cura/Settings/MachineManager.py +++ b/cura/Settings/MachineManager.py @@ -20,6 +20,7 @@ from UM.Settings.SettingDefinition import SettingDefinition from UM.Settings.SettingFunction import SettingFunction from UM.Settings.Validator import ValidatorState from UM.Signal import postponeSignals +import UM.FlameProfiler from cura.QualityManager import QualityManager from cura.PrinterOutputDevice import PrinterOutputDevice @@ -855,6 +856,7 @@ class MachineManager(QObject): # # \param quality_name \type{str} the name of the quality. # \return \type{List[Dict]} with keys "stack", "quality" and "quality_changes". + @UM.FlameProfiler.profile def determineQualityAndQualityChangesForQualityType(self, quality_type): quality_manager = QualityManager.getInstance() result = [] From b688178a2ea59115647837c857aa0a70c2f9efdc Mon Sep 17 00:00:00 2001 From: Jack Ha Date: Wed, 10 May 2017 10:56:19 +0200 Subject: [PATCH 5/6] Fix one part of project load - update existing. CURA-3756 --- plugins/3MFReader/ThreeMFWorkspaceReader.py | 96 +++++++++++---------- 1 file changed, 49 insertions(+), 47 deletions(-) diff --git a/plugins/3MFReader/ThreeMFWorkspaceReader.py b/plugins/3MFReader/ThreeMFWorkspaceReader.py index 560ae76dda..c0c3493f71 100755 --- a/plugins/3MFReader/ThreeMFWorkspaceReader.py +++ b/plugins/3MFReader/ThreeMFWorkspaceReader.py @@ -89,7 +89,10 @@ class ThreeMFWorkspaceReader(WorkspaceReader): 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 + if len(global_stack_file_list) != 1: + raise RuntimeError("More than one global stack file found: [%s]" % str(global_stack_file_list)) + + return global_stack_file_list[0], extruder_stack_file_list ## read some info so we can make decisions # \param file_name @@ -195,12 +198,12 @@ class ThreeMFWorkspaceReader(WorkspaceReader): Job.yieldThread() # Load ContainerStack files and ExtruderStack files - container_stack_files, extruder_stack_files = self._determineGlobalAndExtruderStackFiles( + global_stack_file, 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: + for container_stack_file in [global_stack_file] + extruder_stack_files: container_id = self._stripFileToId(container_stack_file) serialized = archive.open(container_stack_file).read().decode("utf-8") if machine_name == "": @@ -408,7 +411,7 @@ class ThreeMFWorkspaceReader(WorkspaceReader): # Get the stack(s) saved in the workspace. Logger.log("d", "Workspace loading is checking stacks containers...") - container_stack_files, extruder_stack_files = self._determineGlobalAndExtruderStackFiles(file_name, + global_stack_file, extruder_stack_files = self._determineGlobalAndExtruderStackFiles(file_name, cura_file_names) global_stack = None @@ -457,52 +460,52 @@ class ThreeMFWorkspaceReader(WorkspaceReader): # load global stack file try: - for container_stack_file in container_stack_files: - container_id = self._stripFileToId(container_stack_file) + container_id = self._stripFileToId(global_stack_file) - # Check if a stack by this ID already exists; - container_stacks = self._container_registry.findContainerStacks(id = container_id) - if container_stacks: - stack = container_stacks[0] - if self._resolve_strategies["machine"] == "override": - # TODO: HACK - # 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_key = container_stacks[0].getMetaDataEntry("network_authentication_key") - container_stacks[0].deserialize(archive.open(container_stack_file).read().decode("utf-8")) - if network_authentication_id: - container_stacks[0].addMetaDataEntry("network_authentication_id", network_authentication_id) - if network_authentication_key: - container_stacks[0].addMetaDataEntry("network_authentication_key", network_authentication_key) - elif self._resolve_strategies["machine"] == "new": - new_id = self.getNewId(container_id) - stack = GlobalStack(new_id) - stack.deserialize(archive.open(container_stack_file).read().decode("utf-8")) + # Check if a stack by this ID already exists; + container_stacks = self._container_registry.findContainerStacks(id = container_id) + if container_stacks: + stack = container_stacks[0] - # Ensure a unique ID and name - stack._id = new_id + if self._resolve_strategies["machine"] == "override": + # TODO: HACK + # 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_key = container_stacks[0].getMetaDataEntry("network_authentication_key") + container_stacks[0].deserialize(archive.open(global_stack_file).read().decode("utf-8")) + if network_authentication_id: + container_stacks[0].addMetaDataEntry("network_authentication_id", network_authentication_id) + if network_authentication_key: + container_stacks[0].addMetaDataEntry("network_authentication_key", network_authentication_key) + elif self._resolve_strategies["machine"] == "new": + new_id = self.getNewId(container_id) + stack = GlobalStack(new_id) + stack.deserialize(archive.open(global_stack_file).read().decode("utf-8")) - # Extruder stacks are "bound" to a machine. If we add the machine as a new one, the id of the - # bound machine also needs to change. - if stack.getMetaDataEntry("machine", None): - stack.setMetaDataEntry("machine", self.getNewId(stack.getMetaDataEntry("machine"))) + # Ensure a unique ID and name + stack._id = new_id - # Only machines need a new name, stacks may be non-unique - stack.setName(self._container_registry.uniqueName(stack.getName())) - container_stacks_added.append(stack) - self._container_registry.addContainer(stack) - else: - Logger.log("w", "Resolve strategy of %s for machine is not supported", self._resolve_strategies["machine"]) - else: - # no existing container stack, so we create a new one - stack = GlobalStack(container_id) - # Deserialize stack by converting read data from bytes to string - stack.deserialize(archive.open(container_stack_file).read().decode("utf-8")) + # Extruder stacks are "bound" to a machine. If we add the machine as a new one, the id of the + # bound machine also needs to change. + if stack.getMetaDataEntry("machine", None): + stack.setMetaDataEntry("machine", self.getNewId(stack.getMetaDataEntry("machine"))) + + # Only machines need a new name, stacks may be non-unique + stack.setName(self._container_registry.uniqueName(stack.getName())) container_stacks_added.append(stack) self._container_registry.addContainer(stack) + else: + Logger.log("w", "Resolve strategy of %s for machine is not supported", self._resolve_strategies["machine"]) + else: + # no existing container stack, so we create a new one + stack = GlobalStack(container_id) + # Deserialize stack by converting read data from bytes to string + stack.deserialize(archive.open(global_stack_file).read().decode("utf-8")) + container_stacks_added.append(stack) + self._container_registry.addContainer(stack) - global_stack = stack - Job.yieldThread() + global_stack = stack + Job.yieldThread() 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. @@ -585,10 +588,9 @@ class ThreeMFWorkspaceReader(WorkspaceReader): # 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 extruder_stack in global_stack.extruders: + if extruder_stack not in extruder_stacks_added: # skip new ones + self._container_registry.removeContainer(extruder_stack.getId()) for stack in extruder_stacks: stack.setNextStack(global_stack) From 801c282c973df8e79ab1b4294da52376712538d9 Mon Sep 17 00:00:00 2001 From: Jaime van Kessel Date: Wed, 10 May 2017 10:59:21 +0200 Subject: [PATCH 6/6] Only update ExtrudersModel when material changes CURA-3780 --- cura/Settings/ExtrudersModel.py | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/cura/Settings/ExtrudersModel.py b/cura/Settings/ExtrudersModel.py index 54bf0df3b6..e24d4d559a 100644 --- a/cura/Settings/ExtrudersModel.py +++ b/cura/Settings/ExtrudersModel.py @@ -116,10 +116,10 @@ class ExtrudersModel(UM.Qt.ListModel.ListModel): active_extruder_stack.containersChanged.connect(self._onExtruderStackContainersChanged) self._active_extruder_stack = active_extruder_stack - def _onExtruderStackContainersChanged(self, container): - # The ExtrudersModel needs to be updated when the material-name or -color changes, because the user identifies extruders by material-name - self._updateExtruders() + if container.getMetaDataEntry("type") == "material": + # The ExtrudersModel needs to be updated when the material-name or -color changes, because the user identifies extruders by material-name + self._updateExtruders() modelChanged = pyqtSignal() @@ -141,7 +141,7 @@ class ExtrudersModel(UM.Qt.ListModel.ListModel): global_container_stack = Application.getInstance().getGlobalContainerStack() if global_container_stack: if self._add_global: - material = global_container_stack.findContainer({ "type": "material" }) + material = global_container_stack.material color = material.getMetaDataEntry("color_code", default = self.defaultColors[0]) if material else self.defaultColors[0] item = { "id": global_container_stack.getId(), @@ -156,9 +156,6 @@ class ExtrudersModel(UM.Qt.ListModel.ListModel): machine_extruder_count = global_container_stack.getProperty("machine_extruder_count", "value") manager = ExtruderManager.getInstance() for extruder in manager.getMachineExtruders(global_container_stack.getId()): - extruder_name = extruder.getName() - material = extruder.findContainer({ "type": "material" }) - variant = extruder.findContainer({"type": "variant"}) position = extruder.getMetaDataEntry("position", default = "0") # Get the position try: position = int(position) @@ -166,6 +163,9 @@ class ExtrudersModel(UM.Qt.ListModel.ListModel): position = -1 if position >= machine_extruder_count: continue + extruder_name = extruder.getName() + material = extruder.material + variant = extruder.variant default_color = self.defaultColors[position] if position >= 0 and position < len(self.defaultColors) else self.defaultColors[0] color = material.getMetaDataEntry("color_code", default = default_color) if material else default_color