WIP: add getQaulityChangesGroup()

This commit is contained in:
Lipu Fei 2018-02-14 09:31:42 +01:00
parent 27169e883c
commit d84ea07e9e
3 changed files with 113 additions and 50 deletions

View file

@ -43,4 +43,4 @@ class ContainerNode:
return self.container return self.container
def __str__(self) -> str: def __str__(self) -> str:
return "ContainerNode[%s]" % self.metadata.get("id") return "%s[%s]" % (self.__class__.__name__, self.metadata.get("id"))

View file

@ -27,30 +27,48 @@ from cura.Machines.ContainerNode import ContainerNode
# #
class QualityChangesGroup: class QualityChangesGroup(ContainerGroup):
__slots__ = ("name", "qc_for_global", "qc_for_extruders_dict")
def __init__(self, name: str): def __init__(self, name: str, parent = None):
self.name = name # type: str super().__init__(name, parent)
self.qc_for_global = None # type: Optional["QualityNode"]
self.qc_for_extruders_dict = dict() # <extruder_id> -> QualityNode def addNode(self, node: "QualityNode"):
# TODO: in 3.2 and earlier, a quality_changes container may have a field called "extruder" which contains the
# extruder definition ID it belongs to. But, in fact, we only need to know the following things:
# 1. which machine a custom profile is suitable for,
# 2. if this profile is for the GlobalStack,
# 3. if this profile is for an ExtruderStack and which one (the position).
#
# So, it is preferred to have a field like this:
# extruder_position = 1
# instead of this:
# extruder = custom_extruder_1
#
# An upgrade needs to be done if we want to do it this way. Before that, we use the extruder's definition
# to figure out its position.
#
extruder_definition_id = node.metadata.get("extruder")
if extruder_definition_id:
container_registry = Application.getInstance().getContainerRegistry()
metadata_list = container_registry.findDefinitionContainersMetadata(id = extruder_definition_id)
if not metadata_list:
raise RuntimeError("%s cannot get metadata for extruder definition [%s]" %
(self, extruder_definition_id))
extruder_definition_metadata = metadata_list[0]
extruder_position = str(extruder_definition_metadata["position"])
if extruder_position in self.nodes_for_extruders:
raise RuntimeError("%s tries to overwrite the existing nodes_for_extruders position [%s] %s with %s" %
(self, extruder_position, self.node_for_global, node))
self.nodes_for_extruders[extruder_position] = node
def addMetadata(self, metadata: dict):
extruder_id = metadata.get("extruder")
if extruder_id is not None:
self.qc_for_extruders_dict[extruder_id] = QualityNode(metadata)
else: else:
self.qc_for_global = QualityNode(metadata) # This is a quality_changes for the GlobalStack
if self.node_for_global is not None:
def getContainerForGlobalStack(self) -> "InstanceContainer": raise RuntimeError("%s tries to overwrite the existing node_for_global %s with %s" %
return self.qc_for_global.getContainer() (self, self.node_for_global, node))
self.node_for_global = node
def getContainerForExtruderStack(self, extruder_definition_id: str) -> Optional["InstanceContainer"]:
qc_node = self.qc_for_extruders_dict.get(extruder_definition_id)
container = None
if qc_node is not None:
container = qc_node.getContainer()
return container
class QualityGroup(ContainerGroup): class QualityGroup(ContainerGroup):
@ -60,20 +78,20 @@ class QualityGroup(ContainerGroup):
self.quality_type = quality_type self.quality_type = quality_type
self.is_available = False self.is_available = False
#
# QualityNode is used for BOTH quality and quality_changes containers.
#
class QualityNode(ContainerNode): class QualityNode(ContainerNode):
__slots__ = ("metadata", "container", "quality_type_map", "children_map")
def __init__(self, metadata = None): def __init__(self, metadata: Optional[dict] = None):
super().__init__(metadata = metadata) super().__init__(metadata = metadata)
self.quality_type_map = {} self.quality_type_map = {} # quality_type -> QualityNode for InstanceContainer
def addQualityMetadata(self, quality_type: str, metadata: dict): def addQualityMetadata(self, quality_type: str, metadata: dict):
if quality_type not in self.quality_type_map: if quality_type not in self.quality_type_map:
self.quality_type_map[quality_type] = QualityNode(metadata) self.quality_type_map[quality_type] = QualityNode(metadata)
def getQualityNode(self, quality_type: str): def getQualityNode(self, quality_type: str) -> Optional["QualityNode"]:
return self.quality_type_map.get(quality_type) return self.quality_type_map.get(quality_type)
def addQualityChangesMetadata(self, quality_type: str, metadata: dict): def addQualityChangesMetadata(self, quality_type: str, metadata: dict):
@ -84,8 +102,8 @@ class QualityNode(ContainerNode):
name = metadata["name"] name = metadata["name"]
if name not in quality_type_node.children_map: if name not in quality_type_node.children_map:
quality_type_node.children_map[name] = QualityChangesGroup(name) quality_type_node.children_map[name] = QualityChangesGroup(name)
qc_group = quality_type_node.children_map[name] quality_changes_group = quality_type_node.children_map[name]
qc_group.addMetadata(metadata) quality_changes_group.addNode(QualityNode(metadata))
class QualityManager(QObject): class QualityManager(QObject):
@ -164,6 +182,11 @@ class QualityManager(QObject):
material_node.addQualityMetadata(quality_type, metadata) material_node.addQualityMetadata(quality_type, metadata)
# Initialize quality
self._initializeQualityChangesTables()
def _initializeQualityChangesTables(self):
# Initialize the lookup tree for quality_changes profiles with following structure: # Initialize the lookup tree for quality_changes profiles with following structure:
# <machine> -> <quality_type> -> <name> # <machine> -> <quality_type> -> <name>
quality_changes_metadata_list = self._container_registry.findContainersMetadata(type = "quality_changes") quality_changes_metadata_list = self._container_registry.findContainersMetadata(type = "quality_changes")
@ -180,6 +203,51 @@ class QualityManager(QObject):
machine_node.addQualityChangesMetadata(quality_type, metadata) machine_node.addQualityChangesMetadata(quality_type, metadata)
# Updates the given quality groups' availabilities according to which extruders are being used/ enabled.
def _updateQualityGroupsAvailability(self, machine: "GlobalStack", quality_group_list):
used_extruders = set()
# TODO: This will change after the Machine refactoring
for i in range(machine.getProperty("machine_extruder_count", "value")):
used_extruders.add(str(i))
# Update the "is_available" flag for each quality group.
for quality_group in quality_group_list:
is_available = True
if quality_group.node_for_global is None:
is_available = False
if is_available:
for position in used_extruders:
if position not in quality_group.nodes_for_extruders:
is_available = False
break
quality_group.is_available = is_available
# Returns a dict of "custom profile name" -> QualityChangesGroup
def getQualityChangesGroup(self, machine: "GlobalStack") -> dict:
# TODO: How to make this simpler?
# Get machine definition ID
machine_definition_id = self._default_machine_definition_id
if parseBool(machine.getMetaDataEntry("has_machine_quality", False)):
machine_definition_id = machine.getMetaDataEntry("quality_definition")
if machine_definition_id is None:
machine_definition_id = machine.definition.getId()
machine_node = self._machine_quality_type_to_quality_changes_dict.get(machine_definition_id)
if not machine_node:
raise RuntimeError("Cannot find node for machine def [%s] in QualityChanges lookup table" % machine_definition_id)
# iterate over all quality_types in the machine node
quality_changes_group_dict = dict()
for quality_type, quality_changes_node in machine_node.quality_type_map.items():
for quality_changes_name, quality_changes_group in quality_changes_node.children_map.items():
quality_changes_group_dict[quality_changes_name] = quality_changes_group
# Update availabilities for each quality group
self._updateQualityGroupsAvailability(machine, quality_changes_group_dict.values())
return quality_changes_group_dict
def getQualityGroups(self, machine: "GlobalStack") -> dict: def getQualityGroups(self, machine: "GlobalStack") -> dict:
# TODO: How to make this simpler, including the fallbacks. # TODO: How to make this simpler, including the fallbacks.
# Get machine definition ID # Get machine definition ID
@ -191,7 +259,7 @@ class QualityManager(QObject):
machine_node = self._machine_variant_material_quality_type_to_quality_dict.get(machine_definition_id) machine_node = self._machine_variant_material_quality_type_to_quality_dict.get(machine_definition_id)
if not machine_node: if not machine_node:
Logger.log("e", "Cannot find node for machine def [%s] in quality lookup table", machine_definition_id) raise RuntimeError("Cannot find node for machine def [%s] in Quality lookup table" % machine_definition_id)
# iterate over all quality_types in the machine node # iterate over all quality_types in the machine node
quality_group_dict = {} quality_group_dict = {}
@ -268,23 +336,8 @@ class QualityManager(QObject):
quality_group.nodes_for_extruders[position] = quality_node quality_group.nodes_for_extruders[position] = quality_node
used_extruders = set() # Update availabilities for each quality group
# TODO: This will change after the Machine refactoring self._updateQualityGroupsAvailability(machine, quality_group_dict.values())
for i in range(machine.getProperty("machine_extruder_count", "value")):
used_extruders.add(str(i))
# Update the "is_available" flag for each quality group.
for quality_group in quality_group_dict.values():
is_available = True
if quality_group.node_for_global is None:
is_available = False
if is_available:
for position in used_extruders:
if position not in quality_group.nodes_for_extruders:
is_available = False
break
quality_group.is_available = is_available
return quality_group_dict return quality_group_dict

View file

@ -1,5 +1,5 @@
# Copyright (c) 2016 Ultimaker B.V. # Copyright (c) 2018 Ultimaker B.V.
# Cura is released under the terms of the AGPLv3 or higher. # Cura is released under the terms of the LGPLv2 or higher.
from UM.Extension import Extension from UM.Extension import Extension
from PyQt5.QtCore import QObject from PyQt5.QtCore import QObject
@ -12,6 +12,7 @@ class TestTool(Extension, QObject):
self.addMenuItem("Test material manager", self._testMaterialManager) self.addMenuItem("Test material manager", self._testMaterialManager)
self.addMenuItem("Test get quality", self._testGetQuality) self.addMenuItem("Test get quality", self._testGetQuality)
self.addMenuItem("Test get quality changes", self.testGetQualityChanges)
def _testMaterialManager(self): def _testMaterialManager(self):
print("!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!") print("!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!")
@ -24,4 +25,13 @@ class TestTool(Extension, QObject):
result_dict = {} result_dict = {}
global_stack = CuraApplication.getInstance().getMachineManager()._global_container_stack global_stack = CuraApplication.getInstance().getMachineManager()._global_container_stack
result = CuraApplication.getInstance()._quality_manager.getQualityGroups(global_stack) result = CuraApplication.getInstance()._quality_manager.getQualityGroups(global_stack)
print("!!!!!!!!!!!!!!!!!!!")
def testGetQualityChanges(self):
print("!!!!!!!!!!!!!!!!!!!")
from cura.CuraApplication import CuraApplication
result_dict = {}
global_stack = CuraApplication.getInstance().getMachineManager()._global_container_stack
result = CuraApplication.getInstance()._quality_manager.getQualityChangesGroup(global_stack)
print("!!!!!!!!!!!!!!!!!!!")