Have variant nodes build their own children

When a variant and a variant love each other...

Contributes to issue CURA-6600.
This commit is contained in:
Ghostkeeper 2019-08-06 15:11:16 +02:00
parent 65b1a43e88
commit b46d4eb2b5
No known key found for this signature in database
GPG Key ID: 86BEF881AE2CF276
2 changed files with 65 additions and 1 deletions

View File

@ -3,6 +3,7 @@
from typing import TYPE_CHECKING from typing import TYPE_CHECKING
from UM.Util import parseBool
from UM.Settings.ContainerRegistry import ContainerRegistry # To find all the variants for this machine. from UM.Settings.ContainerRegistry import ContainerRegistry # To find all the variants for this machine.
from UM.Settings.Interfaces import ContainerInterface from UM.Settings.Interfaces import ContainerInterface
from cura.Machines.ContainerNode import ContainerNode from cura.Machines.ContainerNode import ContainerNode
@ -19,6 +20,7 @@ class MachineNode(ContainerNode):
super().__init__(container_id, None) super().__init__(container_id, None)
self.variants = {} # type: Dict[str, VariantNode] # mapping variant names to their nodes. self.variants = {} # type: Dict[str, VariantNode] # mapping variant names to their nodes.
container_registry = ContainerRegistry.getInstance() container_registry = ContainerRegistry.getInstance()
self.has_machine_materials = parseBool(container_registry.findContainersMetadata(id = container_id)[0].get("has_machine_materials", "true"))
container_registry.allMetadataLoaded.connect(self._reloadAll) container_registry.allMetadataLoaded.connect(self._reloadAll)
container_registry.containerAdded.connect(self._variantAdded) container_registry.containerAdded.connect(self._variantAdded)
self._reloadAll() self._reloadAll()

View File

@ -3,6 +3,8 @@
from typing import TYPE_CHECKING 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.ContainerNode import ContainerNode
from cura.Machines.MachineNode import MachineNode from cura.Machines.MachineNode import MachineNode
from cura.Machines.MaterialNode import MaterialNode from cura.Machines.MaterialNode import MaterialNode
@ -13,7 +15,67 @@ if TYPE_CHECKING:
## This class represents an extruder variant in the container tree. ## This class represents an extruder variant in the container tree.
# #
# The subnodes of these nodes are materials. # 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): class VariantNode(ContainerNode):
def __init__(self, container_id: str, parent: MachineNode) -> None: def __init__(self, container_id: str, parent: MachineNode) -> None:
super().__init__(container_id, parent) super().__init__(container_id, parent)
self.variants = {} # type: Dict[str, MaterialNode] # mapping variant IDs to their nodes. 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.allMetadataLoaded.connect(self._reloadAll)
container_registry.containerAdded.connect(self._materialAdded)
self._reloadAll()
## (Re)loads all materials under this variant.
def _reloadAll(self):
container_registry = ContainerRegistry.getInstance()
# Find all the materials for this variant's name.
if not self.parent.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.parent.container_id)
variant_specific_materials = container_registry.findInstanceContainersMetadata(type = "material", definition = self.parent.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 material in materials:
base_file = material["base_file"]
if base_file not in self.materials:
self.materials[base_file] = MaterialNode(material["id"], parent = 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.parent.has_machine_materials:
if material_definition != "fdmprinter":
return
base_file = container.getMetaDataEntry("base_file")
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.parent.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.parent.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(), parent = self)