Add "available" flag for quality profiles

CURA-4182

Add "available" flag for quality profile model so the slider can use it
to show available and unavailable profiles.
This commit is contained in:
Lipu Fei 2017-09-13 12:48:48 +02:00
parent 4ed5796e6f
commit 84ad9c6ad1
3 changed files with 84 additions and 10 deletions

View File

@ -82,6 +82,17 @@ class QualityManager:
return list(common_quality_types) return list(common_quality_types)
def findAllQualitiesForMachineAndMaterials(self, machine_definition: "DefinitionContainerInterface", material_containers: List[InstanceContainer]) -> List[InstanceContainer]:
# Determine the common set of quality types which can be
# applied to all of the materials for this machine.
quality_type_dict = self.__fetchQualityTypeDictForMaterial(machine_definition, material_containers[0])
qualities = set(quality_type_dict.values())
for material_container in material_containers[1:]:
next_quality_type_dict = self.__fetchQualityTypeDictForMaterial(machine_definition, material_container)
qualities.update(set(next_quality_type_dict.values()))
return list(qualities)
## Fetches a dict of quality types names to quality profiles for a combination of machine and material. ## Fetches a dict of quality types names to quality profiles for a combination of machine and material.
# #
# \param machine_definition \type{DefinitionContainer} the machine definition. # \param machine_definition \type{DefinitionContainer} the machine definition.
@ -121,7 +132,7 @@ class QualityManager:
# \param material_container \type{InstanceContainer} the material. # \param material_container \type{InstanceContainer} the material.
# \return \type{List[InstanceContainer]} the list of suitable qualities. # \return \type{List[InstanceContainer]} the list of suitable qualities.
def findAllQualitiesForMachineMaterial(self, machine_definition: "DefinitionContainerInterface", material_container: InstanceContainer) -> List[InstanceContainer]: def findAllQualitiesForMachineMaterial(self, machine_definition: "DefinitionContainerInterface", material_container: InstanceContainer) -> List[InstanceContainer]:
criteria = {"type": "quality" } criteria = {"type": "quality"}
result = self._getFilteredContainersForStack(machine_definition, [material_container], **criteria) result = self._getFilteredContainersForStack(machine_definition, [material_container], **criteria)
if not result: if not result:
basic_materials = self._getBasicMaterials(material_container) basic_materials = self._getBasicMaterials(material_container)

View File

@ -1,6 +1,8 @@
# Copyright (c) 2016 Ultimaker B.V. # Copyright (c) 2017 Ultimaker B.V.
# Cura is released under the terms of the AGPLv3 or higher. # Cura is released under the terms of the AGPLv3 or higher.
from collections import OrderedDict
from PyQt5.QtCore import Qt from PyQt5.QtCore import Qt
from UM.Application import Application from UM.Application import Application
@ -10,14 +12,19 @@ from UM.Settings.Models.InstanceContainersModel import InstanceContainersModel
from cura.QualityManager import QualityManager from cura.QualityManager import QualityManager
from cura.Settings.ExtruderManager import ExtruderManager from cura.Settings.ExtruderManager import ExtruderManager
## QML Model for listing the current list of valid quality profiles. ## QML Model for listing the current list of valid quality profiles.
# #
class ProfilesModel(InstanceContainersModel): class ProfilesModel(InstanceContainersModel):
LayerHeightRole = Qt.UserRole + 1001 LayerHeightRole = Qt.UserRole + 1001
LayerHeightWithoutUnitRole = Qt.UserRole + 1002
AvailableRole = Qt.UserRole + 1003
def __init__(self, parent = None): def __init__(self, parent = None):
super().__init__(parent) super().__init__(parent)
self.addRoleName(self.LayerHeightRole, "layer_height") self.addRoleName(self.LayerHeightRole, "layer_height")
self.addRoleName(self.LayerHeightWithoutUnitRole, "layer_height_without_unit")
self.addRoleName(self.AvailableRole, "available")
Application.getInstance().globalContainerStackChanged.connect(self._update) Application.getInstance().globalContainerStackChanged.connect(self._update)
@ -47,6 +54,7 @@ class ProfilesModel(InstanceContainersModel):
global_container_stack = Application.getInstance().getGlobalContainerStack() global_container_stack = Application.getInstance().getGlobalContainerStack()
if global_container_stack is None: if global_container_stack is None:
return [] return []
global_stack_definition = global_container_stack.getBottom()
# Get the list of extruders and place the selected extruder at the front of the list. # Get the list of extruders and place the selected extruder at the front of the list.
extruder_manager = ExtruderManager.getInstance() extruder_manager = ExtruderManager.getInstance()
@ -56,10 +64,22 @@ class ProfilesModel(InstanceContainersModel):
extruder_stacks.remove(active_extruder) extruder_stacks.remove(active_extruder)
extruder_stacks = [active_extruder] + extruder_stacks extruder_stacks = [active_extruder] + extruder_stacks
# Fetch the list of useable qualities across all extruders. if ExtruderManager.getInstance().getActiveExtruderStacks():
# Multi-extruder machine detected.
materials = [extruder.material for extruder in extruder_stacks]
else:
# Machine with one extruder.
materials = [global_container_stack.material]
# Fetch the list of usable qualities across all extruders.
# The actual list of quality profiles come from the first extruder in the extruder list. # The actual list of quality profiles come from the first extruder in the extruder list.
return QualityManager.getInstance().findAllUsableQualitiesForMachineAndExtruders(global_container_stack, result = QualityManager.getInstance().findAllQualitiesForMachineAndMaterials(global_stack_definition,
extruder_stacks) materials)
for quality in QualityManager.getInstance().findAllUsableQualitiesForMachineAndExtruders(
global_container_stack, extruder_stacks):
if quality not in result:
result.append(quality)
return result
## Re-computes the items in this model, and adds the layer height role. ## Re-computes the items in this model, and adds the layer height role.
def _recomputeItems(self): def _recomputeItems(self):
@ -67,6 +87,17 @@ class ProfilesModel(InstanceContainersModel):
global_container_stack = Application.getInstance().getGlobalContainerStack() global_container_stack = Application.getInstance().getGlobalContainerStack()
if global_container_stack is None: if global_container_stack is None:
return return
# Get the list of extruders and place the selected extruder at the front of the list.
extruder_manager = ExtruderManager.getInstance()
active_extruder = extruder_manager.getActiveExtruderStack()
extruder_stacks = extruder_manager.getActiveExtruderStacks()
if active_extruder in extruder_stacks:
extruder_stacks.remove(active_extruder)
extruder_stacks = [active_extruder] + extruder_stacks
# Get a list of available qualities for this machine and material
qualities = QualityManager.getInstance().findAllUsableQualitiesForMachineAndExtruders(global_container_stack,
extruder_stacks)
container_registry = ContainerRegistry.getInstance() container_registry = ContainerRegistry.getInstance()
machine_manager = Application.getInstance().getMachineManager() machine_manager = Application.getInstance().getMachineManager()
@ -74,17 +105,44 @@ class ProfilesModel(InstanceContainersModel):
if not unit: if not unit:
unit = "" unit = ""
# group all quality items according to quality_types, so we know which profile suits the currently
# active machine and material, and later yield the right ones.
tmp_all_quality_items = OrderedDict()
for item in super()._recomputeItems(): for item in super()._recomputeItems():
profile = container_registry.findContainers(id = item["id"])
quality_type = profile[0].getMetaDataEntry("quality_type") if profile else ""
if quality_type not in tmp_all_quality_items:
tmp_all_quality_items[quality_type] = {"suitable_container": None,
"all_containers": []}
tmp_all_quality_items[quality_type]["all_containers"].append(item)
if tmp_all_quality_items[quality_type]["suitable_container"] is None and profile[0] in qualities:
tmp_all_quality_items[quality_type]["suitable_container"] = item
# reverse the ordering (finest first, coarsest last)
all_quality_items = OrderedDict()
for key in reversed(tmp_all_quality_items.keys()):
all_quality_items[key] = tmp_all_quality_items[key]
for data_item in all_quality_items.values():
item = data_item["suitable_container"]
if item is None:
item = data_item["all_containers"][0]
profile = container_registry.findContainers(id = item["id"]) profile = container_registry.findContainers(id = item["id"])
if not profile: if not profile:
item["layer_height"] = "" #Can't update a profile that is unknown. item["layer_height"] = "" #Can't update a profile that is unknown.
item["available"] = False
yield item yield item
continue continue
#Easy case: This profile defines its own layer height.
profile = profile[0] profile = profile[0]
item["available"] = profile in qualities
#Easy case: This profile defines its own layer height.
if profile.hasProperty("layer_height", "value"): if profile.hasProperty("layer_height", "value"):
item["layer_height"] = str(profile.getProperty("layer_height", "value")) + unit self._setItemLayerHeight(item, profile.getProperty("layer_height", "value"), unit)
yield item yield item
continue continue
@ -102,7 +160,7 @@ class ProfilesModel(InstanceContainersModel):
else: else:
quality = None quality = None
if quality and quality.hasProperty("layer_height", "value"): if quality and quality.hasProperty("layer_height", "value"):
item["layer_height"] = str(quality.getProperty("layer_height", "value")) + unit self._setItemLayerHeight(item, quality.getProperty("layer_height", "value"), unit)
yield item yield item
continue continue
@ -112,5 +170,9 @@ class ProfilesModel(InstanceContainersModel):
skip_until_container = global_container_stack.variant skip_until_container = global_container_stack.variant
if not skip_until_container or skip_until_container == ContainerRegistry.getInstance().getEmptyInstanceContainer(): #No variant in stack. if not skip_until_container or skip_until_container == ContainerRegistry.getInstance().getEmptyInstanceContainer(): #No variant in stack.
skip_until_container = global_container_stack.getBottom() skip_until_container = global_container_stack.getBottom()
item["layer_height"] = str(global_container_stack.getRawProperty("layer_height", "value", skip_until_container = skip_until_container.getId())) + unit #Fall through to the currently loaded material. self._setItemLayerHeight(item, global_container_stack.getRawProperty("layer_height", "value", skip_until_container = skip_until_container.getId()), unit) # Fall through to the currently loaded material.
yield item yield item
def _setItemLayerHeight(self, item, value, unit):
item["layer_height"] = str(value) + unit
item["layer_height_without_unit"] = str(value)

View File

@ -22,6 +22,7 @@ Menu
checked: Cura.MachineManager.activeQualityChangesId == "" && Cura.MachineManager.activeQualityType == model.metadata.quality_type checked: Cura.MachineManager.activeQualityChangesId == "" && Cura.MachineManager.activeQualityType == model.metadata.quality_type
exclusiveGroup: group exclusiveGroup: group
onTriggered: Cura.MachineManager.setActiveQuality(model.id) onTriggered: Cura.MachineManager.setActiveQuality(model.id)
visible: model.available
} }
onObjectAdded: menu.insertItem(index, object); onObjectAdded: menu.insertItem(index, object);