From 5b8ed91b04d88667e9d32604200752cb5bcbefdc Mon Sep 17 00:00:00 2001 From: Ghostkeeper Date: Tue, 27 Aug 2019 13:50:48 +0200 Subject: [PATCH 1/7] Create new MaterialManagementModel and move canMaterialBeRemoved Just like the QualityManagementModel, this class is intended to be used as proxy for the material management page in the preferences. I'm intending to move all relevant pyqtSlots from the material manager into this one. The advantage of this switch is that the material manager had no well-bounded scope and so tended to become a big mess of all sorts of functions. This one has a clear scope: serve as a proxy for the buttons you can press in the preferences screen for materials. Contributes to issue CURA-6600. --- cura/CuraApplication.py | 2 ++ cura/Machines/MaterialManager.py | 10 +++--- .../Models/MaterialManagementModel.py | 33 +++++++++++++++++++ .../Preferences/Materials/MaterialsPage.qml | 9 +++-- 4 files changed, 46 insertions(+), 8 deletions(-) create mode 100644 cura/Machines/Models/MaterialManagementModel.py diff --git a/cura/CuraApplication.py b/cura/CuraApplication.py index c9d2163609..e378224a04 100755 --- a/cura/CuraApplication.py +++ b/cura/CuraApplication.py @@ -85,6 +85,7 @@ from cura.Machines.Models.FirstStartMachineActionsModel import FirstStartMachine from cura.Machines.Models.GenericMaterialsModel import GenericMaterialsModel from cura.Machines.Models.GlobalStacksModel import GlobalStacksModel from cura.Machines.Models.MaterialBrandsModel import MaterialBrandsModel +from cura.Machines.Models.MaterialManagementModel import MaterialManagementModel from cura.Machines.Models.MultiBuildPlateModel import MultiBuildPlateModel from cura.Machines.Models.NozzleModel import NozzleModel from cura.Machines.Models.QualityManagementModel import QualityManagementModel @@ -1054,6 +1055,7 @@ class CuraApplication(QtApplication): qmlRegisterType(GenericMaterialsModel, "Cura", 1, 0, "GenericMaterialsModel") qmlRegisterType(MaterialBrandsModel, "Cura", 1, 0, "MaterialBrandsModel") qmlRegisterType(QualityManagementModel, "Cura", 1, 0, "QualityManagementModel") + qmlRegisterType(MaterialManagementModel, "Cura", 1, 5, "MaterialManagementModel") qmlRegisterType(DiscoveredPrintersModel, "Cura", 1, 0, "DiscoveredPrintersModel") diff --git a/cura/Machines/MaterialManager.py b/cura/Machines/MaterialManager.py index b19c8b7926..24995e417b 100644 --- a/cura/Machines/MaterialManager.py +++ b/cura/Machines/MaterialManager.py @@ -1,5 +1,6 @@ # Copyright (c) 2019 Ultimaker B.V. # Cura is released under the terms of the LGPLv3 or higher. + from collections import defaultdict import copy import uuid @@ -7,19 +8,16 @@ from typing import Dict, Optional, TYPE_CHECKING, Any, List, cast from PyQt5.Qt import QTimer, QObject, pyqtSignal, pyqtSlot -from UM.ConfigurationErrorMessage import ConfigurationErrorMessage from UM.Decorators import deprecated from UM.Logger import Logger from UM.Settings.ContainerRegistry import ContainerRegistry -from UM.Settings.SettingFunction import SettingFunction from UM.Util import parseBool -import cura.CuraApplication #Imported like this to prevent circular imports. +import cura.CuraApplication # Imported like this to prevent circular imports. from cura.Machines.ContainerTree import ContainerTree from cura.Settings.CuraContainerRegistry import CuraContainerRegistry from .MaterialNode import MaterialNode from .MaterialGroup import MaterialGroup -from .VariantType import VariantType if TYPE_CHECKING: from UM.Settings.DefinitionContainer import DefinitionContainer @@ -260,8 +258,8 @@ class MaterialManager(QObject): # Check if the material is active in any extruder train. In that case, the material shouldn't be removed! # In the future we might enable this again, but right now, it's causing a ton of issues if we do (since it # corrupts the configuration) - root_material_id = material_node.container.getMetaDataEntry("base_file") - ids_to_remove = [metadata.get("id", "") for metadata in CuraContainerRegistry.getInstance().findInstanceContainersMetadata(base_file=root_material_id)] + root_material_id = material_node.base_file + ids_to_remove = {metadata.get("id", "") for metadata in CuraContainerRegistry.getInstance().findInstanceContainersMetadata(base_file = root_material_id)} for extruder_stack in CuraContainerRegistry.getInstance().findContainerStacks(type = "extruder_train"): if extruder_stack.material.getId() in ids_to_remove: diff --git a/cura/Machines/Models/MaterialManagementModel.py b/cura/Machines/Models/MaterialManagementModel.py new file mode 100644 index 0000000000..9cc7cb07c9 --- /dev/null +++ b/cura/Machines/Models/MaterialManagementModel.py @@ -0,0 +1,33 @@ +# Copyright (c) 2019 Ultimaker B.V. +# Cura is released under the terms of the LGPLv3 or higher. + +from PyQt5.QtCore import QObject, pyqtSlot # To allow the preference page proxy to be used from the actual preferences page. +from typing import TYPE_CHECKING + +from cura.Settings.CuraContainerRegistry import CuraContainerRegistry # To find the sets of materials belonging to each other, and currently loaded extruder stacks. + +if TYPE_CHECKING: + from cura.Machines.MaterialNode import MaterialNode + +## Proxy class to the materials page in the preferences. +# +# This class handles the actions in that page, such as creating new materials, +# renaming them, etc. +class MaterialManagementModel(QObject): + ## Can a certain material be deleted, or is it still in use in one of the + # container stacks anywhere? + # + # We forbid the user from deleting a material if it's in use in any stack. + # Deleting it while it's in use can lead to corrupted stacks. In the + # future we might enable this functionality again (deleting the material + # from those stacks) but for now it is easier to prevent the user from + # doing this. + # \return Whether or not the material can be removed. + @pyqtSlot("QVariant", result = bool) + def canMaterialBeRemoved(self, material_node: "MaterialNode"): + container_registry = CuraContainerRegistry.getInstance() + ids_to_remove = {metadata.get("id", "") for metadata in container_registry.findInstanceContainersMetadata(base_file = material_node.base_file)} + for extruder_stack in container_registry.findContainerStacks(type = "extruder_train"): + if extruder_stack.material.getId() in ids_to_remove: + return False + return True \ No newline at end of file diff --git a/resources/qml/Preferences/Materials/MaterialsPage.qml b/resources/qml/Preferences/Materials/MaterialsPage.qml index 481a256501..80d746351c 100644 --- a/resources/qml/Preferences/Materials/MaterialsPage.qml +++ b/resources/qml/Preferences/Materials/MaterialsPage.qml @@ -7,7 +7,7 @@ import QtQuick.Layouts 1.3 import QtQuick.Dialogs 1.2 import UM 1.2 as UM -import Cura 1.0 as Cura +import Cura 1.5 as Cura Item { @@ -42,6 +42,11 @@ Item name: "cura" } + Cura.MaterialManagementModel + { + id: materialManagement + } + function resetExpandedActiveMaterial() { materialListView.expandActiveMaterial(active_root_material_id) @@ -147,7 +152,7 @@ Item id: removeMenuButton text: catalog.i18nc("@action:button", "Remove") iconName: "list-remove" - enabled: base.hasCurrentItem && !base.currentItem.is_read_only && !base.isCurrentItemActivated && base.materialManager.canMaterialBeRemoved(base.currentItem.container_node) + enabled: base.hasCurrentItem && !base.currentItem.is_read_only && !base.isCurrentItemActivated && materialManagement.canMaterialBeRemoved(base.currentItem.container_node) onClicked: { From 99ccddefa4824d010214b3693a717183f9a534d6 Mon Sep 17 00:00:00 2001 From: Ghostkeeper Date: Tue, 27 Aug 2019 14:26:06 +0200 Subject: [PATCH 2/7] Move setMaterialName to MaterialManagementModel No longer use the material manager which is deprecated. Contributes to issue CURA-6600. --- cura/Machines/Models/MaterialManagementModel.py | 17 ++++++++++++++++- .../qml/Preferences/Materials/MaterialsView.qml | 2 +- 2 files changed, 17 insertions(+), 2 deletions(-) diff --git a/cura/Machines/Models/MaterialManagementModel.py b/cura/Machines/Models/MaterialManagementModel.py index 9cc7cb07c9..1b7774c4d3 100644 --- a/cura/Machines/Models/MaterialManagementModel.py +++ b/cura/Machines/Models/MaterialManagementModel.py @@ -4,6 +4,8 @@ from PyQt5.QtCore import QObject, pyqtSlot # To allow the preference page proxy to be used from the actual preferences page. from typing import TYPE_CHECKING +from UM.Logger import Logger + from cura.Settings.CuraContainerRegistry import CuraContainerRegistry # To find the sets of materials belonging to each other, and currently loaded extruder stacks. if TYPE_CHECKING: @@ -22,6 +24,7 @@ class MaterialManagementModel(QObject): # future we might enable this functionality again (deleting the material # from those stacks) but for now it is easier to prevent the user from # doing this. + # \param material_node The ContainerTree node of the material to check. # \return Whether or not the material can be removed. @pyqtSlot("QVariant", result = bool) def canMaterialBeRemoved(self, material_node: "MaterialNode"): @@ -30,4 +33,16 @@ class MaterialManagementModel(QObject): for extruder_stack in container_registry.findContainerStacks(type = "extruder_train"): if extruder_stack.material.getId() in ids_to_remove: return False - return True \ No newline at end of file + return True + + ## Change the user-visible name of a material. + # \param material_node The ContainerTree node of the material to rename. + # \param name The new name for the material. + @pyqtSlot("QVariant", str) + def setMaterialName(self, material_node: "MaterialNode", name: str) -> None: + container_registry = CuraContainerRegistry.getInstance() + root_material_id = material_node.base_file + if container_registry.isReadOnly(root_material_id): + Logger.log("w", "Cannot set name of read-only container %s.", root_material_id) + return + return container_registry.findContainers(id = root_material_id)[0].setName(name) \ No newline at end of file diff --git a/resources/qml/Preferences/Materials/MaterialsView.qml b/resources/qml/Preferences/Materials/MaterialsView.qml index 30b2474e09..8302f5f65a 100644 --- a/resources/qml/Preferences/Materials/MaterialsView.qml +++ b/resources/qml/Preferences/Materials/MaterialsView.qml @@ -565,7 +565,7 @@ TabView } // update the values - CuraApplication.getMaterialManager().setMaterialName(base.currentMaterialNode, new_name) + base.materialManagement.setMaterialName(base.currentMaterialNode, new_name) properties.name = new_name } From 3dc7c7b61c4c354ceb7fe16b84cb0bbacf434372 Mon Sep 17 00:00:00 2001 From: Ghostkeeper Date: Tue, 27 Aug 2019 14:53:50 +0200 Subject: [PATCH 3/7] Move removeMaterial to MaterialManagementModel Moving away from the MaterialManager. Contributes to issue CURA-6600. --- cura/Machines/MaterialManager.py | 2 +- .../Models/MaterialManagementModel.py | 19 ++++++++++++++++++- .../Preferences/Materials/MaterialsPage.qml | 2 +- .../Preferences/Materials/MaterialsView.qml | 2 +- 4 files changed, 21 insertions(+), 4 deletions(-) diff --git a/cura/Machines/MaterialManager.py b/cura/Machines/MaterialManager.py index 24995e417b..5d5938d95d 100644 --- a/cura/Machines/MaterialManager.py +++ b/cura/Machines/MaterialManager.py @@ -246,7 +246,7 @@ class MaterialManager(QObject): def removeMaterialByRootId(self, root_material_id: str): container_registry = CuraContainerRegistry.getInstance() - results = container_registry.findContainers(id=root_material_id) + results = container_registry.findContainers(id = root_material_id) if not results: container_registry.addWrongContainerId(root_material_id) diff --git a/cura/Machines/Models/MaterialManagementModel.py b/cura/Machines/Models/MaterialManagementModel.py index 1b7774c4d3..2c8617073d 100644 --- a/cura/Machines/Models/MaterialManagementModel.py +++ b/cura/Machines/Models/MaterialManagementModel.py @@ -45,4 +45,21 @@ class MaterialManagementModel(QObject): if container_registry.isReadOnly(root_material_id): Logger.log("w", "Cannot set name of read-only container %s.", root_material_id) return - return container_registry.findContainers(id = root_material_id)[0].setName(name) \ No newline at end of file + return container_registry.findContainers(id = root_material_id)[0].setName(name) + + ## Deletes a material from Cura. + # + # This function does not do any safety checking any more. Please call this + # function only if: + # - The material is not read-only. + # - The material is not used in any stacks. + # If the material was not lazy-loaded yet, this will fully load the + # container. When removing this material node, all other materials with + # the same base fill will also be removed. + # \param material_node The material to remove. + @pyqtSlot("QVariant") + def removeMaterial(self, material_node: "MaterialNode") -> None: + container_registry = CuraContainerRegistry.getInstance() + materials_this_base_file = container_registry.findContainersMetadata(base_file = material_node.base_file) + for material_metadata in materials_this_base_file: + container_registry.removeContainer(material_metadata["id"]) \ No newline at end of file diff --git a/resources/qml/Preferences/Materials/MaterialsPage.qml b/resources/qml/Preferences/Materials/MaterialsPage.qml index 80d746351c..3453c866e3 100644 --- a/resources/qml/Preferences/Materials/MaterialsPage.qml +++ b/resources/qml/Preferences/Materials/MaterialsPage.qml @@ -302,7 +302,7 @@ Item { // Set the active material as the fallback. It will be selected when the current material is deleted base.newRootMaterialIdToSwitchTo = base.active_root_material_id - base.materialManager.removeMaterial(base.currentItem.container_node); + base.materialManagement.removeMaterial(base.currentItem.container_node); } } diff --git a/resources/qml/Preferences/Materials/MaterialsView.qml b/resources/qml/Preferences/Materials/MaterialsView.qml index 8302f5f65a..83c7de9aee 100644 --- a/resources/qml/Preferences/Materials/MaterialsView.qml +++ b/resources/qml/Preferences/Materials/MaterialsView.qml @@ -565,7 +565,7 @@ TabView } // update the values - base.materialManagement.setMaterialName(base.currentMaterialNode, new_name) + materialManagement.setMaterialName(base.currentMaterialNode, new_name) properties.name = new_name } From b60b13e5bfaf43dec47d94e58da13554721dd765 Mon Sep 17 00:00:00 2001 From: Ghostkeeper Date: Tue, 27 Aug 2019 15:06:44 +0200 Subject: [PATCH 4/7] Use container tree to check for variants when serialising Not the variant manager, because it's deprecated. Contributes to issue CURA-6600. --- .../XmlMaterialProfile/XmlMaterialProfile.py | 19 +++++++++---------- 1 file changed, 9 insertions(+), 10 deletions(-) diff --git a/plugins/XmlMaterialProfile/XmlMaterialProfile.py b/plugins/XmlMaterialProfile/XmlMaterialProfile.py index 157d871d54..4c1920a97e 100644 --- a/plugins/XmlMaterialProfile/XmlMaterialProfile.py +++ b/plugins/XmlMaterialProfile/XmlMaterialProfile.py @@ -226,7 +226,7 @@ class XmlMaterialProfile(InstanceContainer): machine_container_map = {} # type: Dict[str, InstanceContainer] machine_variant_map = {} # type: Dict[str, Dict[str, Any]] - variant_manager = CuraApplication.getInstance().getVariantManager() + container_tree = ContainerTree.getInstance() root_material_id = self.getMetaDataEntry("base_file") # if basefile is self.getId, this is a basefile. all_containers = registry.findInstanceContainers(base_file = root_material_id) @@ -243,16 +243,15 @@ class XmlMaterialProfile(InstanceContainer): machine_variant_map[definition_id] = {} variant_name = container.getMetaDataEntry("variant_name") - if variant_name: - variant_node = variant_manager.getVariantNode(definition_id, variant_name) - if variant_node is None: - continue - variant_dict = {"variant_node":variant_node , - "material_container": container} - machine_variant_map[definition_id][variant_name] = variant_dict - continue + if not variant_name: + machine_container_map[definition_id] = container - machine_container_map[definition_id] = container + if variant_name not in container_tree.machines[definition_id].variants: + continue + variant_node = container_tree.machines[definition_id].variants[variant_name] + variant_dict = {"variant_node": variant_node, + "material_container": container} + machine_variant_map[definition_id][variant_name] = variant_dict # Map machine human-readable names to IDs product_id_map = self.getProductIdMap() From 8346e465f65c3cef248ab22b4aa643f3cb1898e3 Mon Sep 17 00:00:00 2001 From: Ghostkeeper Date: Tue, 27 Aug 2019 15:22:28 +0200 Subject: [PATCH 5/7] Turn MaterialManagementModel into a singleton Just like MaterialManager used to be. There can be only one instance of the page then. This prevents a crash when Qt deletes the QObject because it's no longer used in the page when you close the preferences screen. But when you open it again it doesn't construct a new one. Now there is always one instance so that's not a problem any more. Also it allows other pages to access this item. Contributes to issue CURA-6600. --- cura/CuraApplication.py | 7 ++++++- resources/qml/Preferences/Materials/MaterialsPage.qml | 10 +++------- resources/qml/Preferences/Materials/MaterialsView.qml | 3 ++- 3 files changed, 11 insertions(+), 9 deletions(-) diff --git a/cura/CuraApplication.py b/cura/CuraApplication.py index e378224a04..c452c56cf5 100755 --- a/cura/CuraApplication.py +++ b/cura/CuraApplication.py @@ -222,6 +222,7 @@ class CuraApplication(QtApplication): self._machine_error_checker = None self._machine_settings_manager = MachineSettingsManager(self, parent = self) + self._material_management_model = MaterialManagementModel() self._discovered_printer_model = DiscoveredPrintersModel(self, parent = self) self._first_start_machine_actions_model = FirstStartMachineActionsModel(self, parent = self) @@ -976,6 +977,10 @@ class CuraApplication(QtApplication): def getMachineActionManager(self, *args): return self._machine_action_manager + @pyqtSlot(result = QObject) + def getMaterialManagementModel(self): + return self._material_management_model + def getSimpleModeSettingsManager(self, *args): if self._simple_mode_settings_manager is None: self._simple_mode_settings_manager = SimpleModeSettingsManager() @@ -1055,7 +1060,7 @@ class CuraApplication(QtApplication): qmlRegisterType(GenericMaterialsModel, "Cura", 1, 0, "GenericMaterialsModel") qmlRegisterType(MaterialBrandsModel, "Cura", 1, 0, "MaterialBrandsModel") qmlRegisterType(QualityManagementModel, "Cura", 1, 0, "QualityManagementModel") - qmlRegisterType(MaterialManagementModel, "Cura", 1, 5, "MaterialManagementModel") + qmlRegisterSingletonType(MaterialManagementModel, "Cura", 1, 5, "MaterialManagementModel", self.getMaterialManagementModel) qmlRegisterType(DiscoveredPrintersModel, "Cura", 1, 0, "DiscoveredPrintersModel") diff --git a/resources/qml/Preferences/Materials/MaterialsPage.qml b/resources/qml/Preferences/Materials/MaterialsPage.qml index 3453c866e3..4a6ff75f0d 100644 --- a/resources/qml/Preferences/Materials/MaterialsPage.qml +++ b/resources/qml/Preferences/Materials/MaterialsPage.qml @@ -18,6 +18,7 @@ Item property var currentItem: null property var materialManager: CuraApplication.getMaterialManager() + property var materialManagementModel: CuraApplication.getMaterialManagementModel() property var hasCurrentItem: base.currentItem != null property var isCurrentItemActivated: @@ -42,11 +43,6 @@ Item name: "cura" } - Cura.MaterialManagementModel - { - id: materialManagement - } - function resetExpandedActiveMaterial() { materialListView.expandActiveMaterial(active_root_material_id) @@ -152,7 +148,7 @@ Item id: removeMenuButton text: catalog.i18nc("@action:button", "Remove") iconName: "list-remove" - enabled: base.hasCurrentItem && !base.currentItem.is_read_only && !base.isCurrentItemActivated && materialManagement.canMaterialBeRemoved(base.currentItem.container_node) + enabled: base.hasCurrentItem && !base.currentItem.is_read_only && !base.isCurrentItemActivated && base.materialManagementModel.canMaterialBeRemoved(base.currentItem.container_node) onClicked: { @@ -302,7 +298,7 @@ Item { // Set the active material as the fallback. It will be selected when the current material is deleted base.newRootMaterialIdToSwitchTo = base.active_root_material_id - base.materialManagement.removeMaterial(base.currentItem.container_node); + base.materialManagementModel.removeMaterial(base.currentItem.container_node); } } diff --git a/resources/qml/Preferences/Materials/MaterialsView.qml b/resources/qml/Preferences/Materials/MaterialsView.qml index 83c7de9aee..0f5eba2f2f 100644 --- a/resources/qml/Preferences/Materials/MaterialsView.qml +++ b/resources/qml/Preferences/Materials/MaterialsView.qml @@ -23,6 +23,7 @@ TabView property real secondColumnWidth: (width * 0.40) | 0 property string containerId: "" property var materialPreferenceValues: UM.Preferences.getValue("cura/material_settings") ? JSON.parse(UM.Preferences.getValue("cura/material_settings")) : {} + property var materialManagementModel: CuraApplication.getMaterialManagementModel() property double spoolLength: calculateSpoolLength() property real costPerMeter: calculateCostPerMeter() @@ -565,7 +566,7 @@ TabView } // update the values - materialManagement.setMaterialName(base.currentMaterialNode, new_name) + base.materialManagementModel.setMaterialName(base.currentMaterialNode, new_name) properties.name = new_name } From 63ae6ee9ec874f734ad28975fe2866b0df8d03b9 Mon Sep 17 00:00:00 2001 From: Ghostkeeper Date: Tue, 27 Aug 2019 15:33:39 +0200 Subject: [PATCH 6/7] Fix updating materials models when materials change before first printer switch Otherwise the _extruder_stack field would not yet be set. Contributes to issue CURA-6600. --- cura/Machines/Models/BaseMaterialsModel.py | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/cura/Machines/Models/BaseMaterialsModel.py b/cura/Machines/Models/BaseMaterialsModel.py index 3ab11b7e9d..81be676a33 100644 --- a/cura/Machines/Models/BaseMaterialsModel.py +++ b/cura/Machines/Models/BaseMaterialsModel.py @@ -31,8 +31,13 @@ class BaseMaterialsModel(ListModel): self._container_registry = self._application.getInstance().getContainerRegistry() self._machine_manager = self._application.getMachineManager() + self._extruder_position = 0 + self._extruder_stack = None + self._enabled = True + # Update the stack and the model data when the machine changes self._machine_manager.globalContainerChanged.connect(self._updateExtruderStack) + self._updateExtruderStack() # Update this model when switching machines, when adding materials or changing their metadata. self._machine_manager.activeStackChanged.connect(self._update) @@ -55,12 +60,8 @@ class BaseMaterialsModel(ListModel): self.addRoleName(Qt.UserRole + 15, "container_node") self.addRoleName(Qt.UserRole + 16, "is_favorite") - self._extruder_position = 0 - self._extruder_stack = None - self._available_materials = None # type: Optional[Dict[str, MaterialNode]] self._favorite_ids = set() # type: Set[str] - self._enabled = True def _updateExtruderStack(self): global_stack = self._machine_manager.activeMachine From dabd905853b178856dd2fc8320b4a4633b7fa2f3 Mon Sep 17 00:00:00 2001 From: Ghostkeeper Date: Tue, 27 Aug 2019 15:47:23 +0200 Subject: [PATCH 7/7] Fix serialising materials with submaterials in not loaded container trees Material profiles need to serialise subprofiles that belong to different printers as well. Some of these materials may not be loaded in the ContainerTree structure. To prevent having to load that as well, we're just not going to use the container tree any more. It turns out that the only reason it was using the container tree was to get the hardware_type metadata from the node in the tree. So just get that from the container itself and we're fine. Contributes to issue CURA-6600. --- plugins/XmlMaterialProfile/XmlMaterialProfile.py | 12 ++++-------- 1 file changed, 4 insertions(+), 8 deletions(-) diff --git a/plugins/XmlMaterialProfile/XmlMaterialProfile.py b/plugins/XmlMaterialProfile/XmlMaterialProfile.py index 4c1920a97e..ac53564eaf 100644 --- a/plugins/XmlMaterialProfile/XmlMaterialProfile.py +++ b/plugins/XmlMaterialProfile/XmlMaterialProfile.py @@ -223,8 +223,8 @@ class XmlMaterialProfile(InstanceContainer): for instance in self.findInstances(): self._addSettingElement(builder, instance) - machine_container_map = {} # type: Dict[str, InstanceContainer] - machine_variant_map = {} # type: Dict[str, Dict[str, Any]] + machine_container_map = {} # type: Dict[str, InstanceContainer] + machine_variant_map = {} # type: Dict[str, Dict[str, Any]] container_tree = ContainerTree.getInstance() @@ -246,10 +246,7 @@ class XmlMaterialProfile(InstanceContainer): if not variant_name: machine_container_map[definition_id] = container - if variant_name not in container_tree.machines[definition_id].variants: - continue - variant_node = container_tree.machines[definition_id].variants[variant_name] - variant_dict = {"variant_node": variant_node, + variant_dict = {"variant_type": container.getMetaDataEntry("hardware_type", str(VariantType.NOZZLE)), "material_container": container} machine_variant_map[definition_id][variant_name] = variant_dict @@ -284,8 +281,7 @@ class XmlMaterialProfile(InstanceContainer): # Find all hotend sub-profiles corresponding to this material and machine and add them to this profile. buildplate_dict = {} # type: Dict[str, Any] for variant_name, variant_dict in machine_variant_map[definition_id].items(): - variant_type = variant_dict["variant_node"].getMetaDataEntry("hardware_type", str(VariantType.NOZZLE)) - variant_type = VariantType(variant_type) + variant_type = VariantType(variant_dict["variant_type"]) if variant_type == VariantType.NOZZLE: # The hotend identifier is not the containers name, but its "name". builder.start("hotend", {"id": variant_name})