Cura/cura/Machines/VariantNode.py
Ghostkeeper 8ec1c31b58
Don't make parent a common property
Instead we use properly-typed and appropriately-named variables in each of the sub classes.

Contributes to issue CURA-6600.
2019-08-06 16:31:57 +02:00

86 lines
5.2 KiB
Python

# Copyright (c) 2019 Ultimaker B.V.
# Cura is released under the terms of the LGPLv3 or higher.
from typing import TYPE_CHECKING
from UM.Settings.ContainerRegistry import ContainerRegistry
from UM.Settings.Interfaces import ContainerInterface
from cura.Machines.ContainerNode import ContainerNode
from cura.Machines.MachineNode import MachineNode
from cura.Machines.MaterialNode import MaterialNode
if TYPE_CHECKING:
from typing import Dict
## This class represents an extruder variant in the container tree.
#
# The subnodes of these nodes are materials.
#
# This node contains materials with ALL filament diameters underneath it. The
# tree of this variant is not specific to one global stack, so because the
# list of materials can be different per stack depending on the compatible
# material diameter setting, we cannot filter them here. Filtering must be
# done in the model.
class VariantNode(ContainerNode):
def __init__(self, container_id: str, machine: MachineNode) -> None:
super().__init__(container_id)
self.machine = machine
self.materials = {} # type: Dict[str, MaterialNode] # Mapping material base files to their nodes.
container_registry = ContainerRegistry.getInstance()
self.variant_name = container_registry.findContainersMetadata(id = container_id)[0]["name"] # Store our own name so that we can filter more easily.
container_registry.containerAdded.connect(self._materialAdded)
self._loadAll()
## (Re)loads all materials under this variant.
def _loadAll(self):
container_registry = ContainerRegistry.getInstance()
# Find all the materials for this variant's name.
if not self.machine.has_machine_materials: # Printer has no specific materials. Look for all fdmprinter materials.
materials = container_registry.findInstanceContainersMetadata(type = "material", definition = "fdmprinter") # These are ONLY the base materials.
else: # Printer has its own material profiles. Look for material profiles with this printer's definition.
all_materials = container_registry.findInstanceContainersMetadata(type = "material", definition = "fdmprinter")
printer_specific_materials = container_registry.findInstanceContainersMetadata(type = "material", definition = self.machine.container_id)
variant_specific_materials = container_registry.findInstanceContainersMetadata(type = "material", definition = self.machine.container_id, variant = self.variant_name)
materials_per_base_file = {material["base_file"]: material for material in all_materials}
materials_per_base_file.update({material["base_file"]: material for material in printer_specific_materials}) # Printer-specific profiles override global ones.
materials_per_base_file.update({material["base_file"]: material for material in variant_specific_materials}) # Variant-specific profiles override all of those.
materials = materials_per_base_file.values()
for excluded_material in self.machine.exclude_materials:
del materials[excluded_material]
for material in materials:
base_file = material["base_file"]
if base_file not in self.materials:
self.materials[base_file] = MaterialNode(material["id"], variant = self)
## When a material gets added to the set of profiles, we need to update our
# tree here.
def _materialAdded(self, container: ContainerInterface):
if container.getMetaDataEntry("type") != "material":
return # Not interested.
material_definition = container.getMetaDataEntry("definition")
if not self.machine.has_machine_materials:
if material_definition != "fdmprinter":
return
base_file = container.getMetaDataEntry("base_file")
if base_file in self.machine.exclude_materials:
return # Material is forbidden for this printer.
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", "empty")
if material_variant != "empty" 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:
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", "empty")
if original_variant != "empty" or container.getMetaDataEntry("variant", "empty") == "empty":
return # Original was already specific or just as unspecific as the new one.
self.materials[base_file] = MaterialNode(container.getId(), variant = self)