From 4277ede64f56bcbcb1e8dc9a411f7b9a7727bdf6 Mon Sep 17 00:00:00 2001 From: Remco Burema Date: Mon, 14 Oct 2019 01:01:19 +0200 Subject: [PATCH 1/5] Fix 1/2 of the duplication material bug. The material is added multiple times to the variant nodes, and overwriting it with the eventual right one was going wrong. This does not solve it entirely (because the less specific one still ends up selected _initially_ because it gets added first, and the order can't be guaranteed. part of CURA-6863 --- cura/Machines/VariantNode.py | 11 +++++------ resources/qml/Preferences/Materials/MaterialsList.qml | 2 +- 2 files changed, 6 insertions(+), 7 deletions(-) diff --git a/cura/Machines/VariantNode.py b/cura/Machines/VariantNode.py index fa0c61bd3d..a9a6608d27 100644 --- a/cura/Machines/VariantNode.py +++ b/cura/Machines/VariantNode.py @@ -1,6 +1,5 @@ # Copyright (c) 2019 Ultimaker B.V. # Cura is released under the terms of the LGPLv3 or higher. - from typing import Optional, TYPE_CHECKING from UM.Logger import Logger @@ -111,18 +110,18 @@ class VariantNode(ContainerNode): 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: + 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. - if new_definition != self.machine.container_id: + 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] - original_variant = original_metadata.get("variant_name", "empty") - if original_variant != "empty" or container.getMetaDataEntry("variant_name", "empty") == "empty": + if "variant_name" in original_metadata or material_variant is not None: return # Original was already specific or just as unspecific as the new one. if "empty_material" in self.materials: diff --git a/resources/qml/Preferences/Materials/MaterialsList.qml b/resources/qml/Preferences/Materials/MaterialsList.qml index 96f6730029..8b82a87820 100644 --- a/resources/qml/Preferences/Materials/MaterialsList.qml +++ b/resources/qml/Preferences/Materials/MaterialsList.qml @@ -114,7 +114,7 @@ Item if (base.toActivateNewMaterial) { var position = Cura.ExtruderManager.activeExtruderIndex - Cura.MachineManager.setMaterial(position, base.currentItem.container_node) + Cura.MachineManager.setMaterialById(position, base.newRootMaterialIdToSwitchTo) } base.newRootMaterialIdToSwitchTo = "" base.toActivateNewMaterial = false From 09dc6ae44aece0c3b4c33d98c87a1e767eb83a4d Mon Sep 17 00:00:00 2001 From: Remco Burema Date: Mon, 14 Oct 2019 01:03:41 +0200 Subject: [PATCH 2/5] Scouting: Try not to spam signals or errors as much. nominally part of CURA-6863 --- cura/PrinterOutput/Models/ExtruderConfigurationModel.py | 7 ++++--- .../qml/Preferences/Materials/MaterialsTypeSection.qml | 1 + 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/cura/PrinterOutput/Models/ExtruderConfigurationModel.py b/cura/PrinterOutput/Models/ExtruderConfigurationModel.py index 04a3c95afd..4a1cf4916f 100644 --- a/cura/PrinterOutput/Models/ExtruderConfigurationModel.py +++ b/cura/PrinterOutput/Models/ExtruderConfigurationModel.py @@ -25,9 +25,10 @@ class ExtruderConfigurationModel(QObject): return self._position def setMaterial(self, material: Optional[MaterialOutputModel]) -> None: - if self._material != material: - self._material = material - self.extruderConfigurationChanged.emit() + if material is None or self._material == material: + return + self._material = material + self.extruderConfigurationChanged.emit() @pyqtProperty(QObject, fset = setMaterial, notify = extruderConfigurationChanged) def activeMaterial(self) -> Optional[MaterialOutputModel]: diff --git a/resources/qml/Preferences/Materials/MaterialsTypeSection.qml b/resources/qml/Preferences/Materials/MaterialsTypeSection.qml index 2c1e2128e1..3c36e12651 100644 --- a/resources/qml/Preferences/Materials/MaterialsTypeSection.qml +++ b/resources/qml/Preferences/Materials/MaterialsTypeSection.qml @@ -21,6 +21,7 @@ Item property var colorsModel: materialType != null ? materialType.colors: null height: childrenRect.height width: parent.width + anchors.left: parent.left Rectangle { id: material_type_header_background From 26a7de5a27d795c229a3a3b09fb0d87ad62176e0 Mon Sep 17 00:00:00 2001 From: Remco Burema Date: Mon, 14 Oct 2019 11:02:58 +0200 Subject: [PATCH 3/5] Fix boolean check. part of CURA-6863 --- cura/Machines/VariantNode.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cura/Machines/VariantNode.py b/cura/Machines/VariantNode.py index a9a6608d27..2fdc847a0a 100644 --- a/cura/Machines/VariantNode.py +++ b/cura/Machines/VariantNode.py @@ -121,7 +121,7 @@ class VariantNode(ContainerNode): 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 not None: + 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: From dd8f6dc10e7b9ab6d263d168ef389d1eed44b7f0 Mon Sep 17 00:00:00 2001 From: Lipu Fei Date: Mon, 14 Oct 2019 12:22:15 +0200 Subject: [PATCH 4/5] Fix ContainerTree reacting to duplicating materials CURA-6863 --- cura/Machines/Models/MaterialManagementModel.py | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/cura/Machines/Models/MaterialManagementModel.py b/cura/Machines/Models/MaterialManagementModel.py index b4f3bb9889..6f6f3906b8 100644 --- a/cura/Machines/Models/MaterialManagementModel.py +++ b/cura/Machines/Models/MaterialManagementModel.py @@ -128,6 +128,20 @@ class MaterialManagementModel(QObject): new_container.getMetaData().update(new_metadata) new_containers.append(new_container) + # CURA-6863: Nodes in ContainerTree will be updated upon ContainerAdded signals, one at a time. It will use the + # best fit material container at the time it sees one. For example, if you duplicate and get generic_pva #2, + # if the node update function sees the containers in the following order: + # + # - generic_pva #2 + # - generic_pva #2_um3_aa04 + # + # It will first use "generic_pva #2" because that's the best fit it has ever seen, and later "generic_pva #2_um3_aa04" + # once it sees that. Because things run in the Qt event loop, they don't happen at the same time. This means if + # between those two events, the ContainerTree will have nodes that contain invalid data. + # + # This sort fixes the problem by emitting the most specific containers first. + new_containers = sorted(new_containers, key = lambda x: x.getId(), reverse = True) + for container_to_add in new_containers: container_to_add.setDirty(True) container_registry.addContainer(container_to_add) From cc64fb0a936b250e37f96bc798d5ebadf6ef29b0 Mon Sep 17 00:00:00 2001 From: Lipu Fei Date: Mon, 14 Oct 2019 14:15:03 +0200 Subject: [PATCH 5/5] Fix variant handling in VariantNode CURA-6863 --- cura/Machines/VariantNode.py | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/cura/Machines/VariantNode.py b/cura/Machines/VariantNode.py index c1297651bd..ef8981a3c2 100644 --- a/cura/Machines/VariantNode.py +++ b/cura/Machines/VariantNode.py @@ -6,9 +6,13 @@ from UM.Logger import Logger from UM.Settings.ContainerRegistry import ContainerRegistry from UM.Settings.Interfaces import ContainerInterface from UM.Signal import Signal + +from cura.Settings.cura_empty_instance_containers import empty_variant_container from cura.Machines.ContainerNode import ContainerNode from cura.Machines.MaterialNode import MaterialNode + import UM.FlameProfiler + if TYPE_CHECKING: from typing import Dict from cura.Machines.MachineNode import MachineNode @@ -110,8 +114,8 @@ class VariantNode(ContainerNode): 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: + material_variant = container.getMetaDataEntry("variant_name", empty_variant_container.getName()) + if 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")