Merge branch 'feature_intent' of github.com:Ultimaker/Cura into feature_intent

This commit is contained in:
Jaime van Kessel 2019-10-04 15:46:41 +02:00
commit b3b28bc330
No known key found for this signature in database
GPG key ID: 3710727397403C91
21 changed files with 266 additions and 118 deletions

View file

@ -8,6 +8,7 @@ from UM.Signal import Signal
from UM.Util import parseBool
from UM.Settings.ContainerRegistry import ContainerRegistry # To find all the variants for this machine.
import cura.CuraApplication # Imported like this to prevent circular dependencies.
from cura.Machines.ContainerNode import ContainerNode
from cura.Machines.QualityChangesGroup import QualityChangesGroup # To construct groups of quality changes profiles that belong together.
from cura.Machines.QualityGroup import QualityGroup # To construct groups of quality profiles that belong together.
@ -74,7 +75,7 @@ class MachineNode(ContainerNode):
qualities_per_type_per_extruder[extruder_nr] = self.global_qualities
else:
# Use the actually specialised quality profiles.
qualities_per_type_per_extruder[extruder_nr] = {node.getMetaDataEntry("quality_type"): node for node in self.variants[variant_name].materials[material_base].qualities.values()}
qualities_per_type_per_extruder[extruder_nr] = {node.quality_type: node for node in self.variants[variant_name].materials[material_base].qualities.values()}
# Create the quality group for each available type.
quality_groups = {}
@ -82,15 +83,7 @@ class MachineNode(ContainerNode):
if not global_quality_node.container:
Logger.log("w", "Node {0} doesn't have a container.".format(global_quality_node.container_id))
continue
# CURA-6599
# Same as QualityChangesGroup.
# For some reason, QML will get null or fail to convert type for MachineManager.activeQualityChangesGroup() to
# a QObject. Setting the object ownership to QQmlEngine.CppOwnership doesn't work, but setting the object
# parent to application seems to work.
from cura.CuraApplication import CuraApplication
quality_groups[quality_type] = QualityGroup(name = global_quality_node.container.getMetaDataEntry("name", "Unnamed profile"),
quality_type = quality_type,
parent = CuraApplication.getInstance())
quality_groups[quality_type] = QualityGroup(name = global_quality_node.getMetaDataEntry("name", "Unnamed profile"), quality_type = quality_type)
quality_groups[quality_type].node_for_global = global_quality_node
for extruder, qualities_per_type in enumerate(qualities_per_type_per_extruder):
if quality_type in qualities_per_type:
@ -170,7 +163,7 @@ class MachineNode(ContainerNode):
## (Re)loads all variants under this printer.
@UM.FlameProfiler.profile
def _loadAll(self):
def _loadAll(self) -> None:
container_registry = ContainerRegistry.getInstance()
if not self.has_variants:
self.variants["empty"] = VariantNode("empty_variant", machine = self)

View file

@ -1,4 +1,4 @@
# Copyright (c) 2018 Ultimaker B.V.
# Copyright (c) 2019 Ultimaker B.V.
# Cura is released under the terms of the LGPLv3 or higher.
from typing import Dict, Optional, List, Set
@ -11,24 +11,28 @@ from UM.Util import parseBool
from cura.Machines.ContainerNode import ContainerNode
## A QualityGroup represents a group of quality containers that must be applied
# to each ContainerStack when it's used.
#
# A QualityGroup represents a group of containers that must be applied to each ContainerStack when it's used.
# Some concrete examples are Quality and QualityChanges: when we select quality type "normal", this quality type
# must be applied to all stacks in a machine, although each stack can have different containers. Use an Ultimaker 3
# as an example, suppose we choose quality type "normal", the actual InstanceContainers on each stack may look
# as below:
# GlobalStack ExtruderStack 1 ExtruderStack 2
# quality container: um3_global_normal um3_aa04_pla_normal um3_aa04_abs_normal
# A concrete example: When there are two extruders and the user selects the
# quality type "normal", this quality type must be applied to all stacks in a
# machine, although each stack can have different containers. So one global
# profile gets put on the global stack and one extruder profile gets put on
# each extruder stack. This quality group then contains the following
# profiles (for instance):
# GlobalStack ExtruderStack 1 ExtruderStack 2
# quality container: um3_global_normal um3_aa04_pla_normal um3_aa04_abs_normal
#
# This QualityGroup is mainly used in quality and quality_changes to group the containers that can be applied to
# a machine, so when a quality/custom quality is selected, the container can be directly applied to each stack instead
# of looking them up again.
#
class QualityGroup(QObject):
def __init__(self, name: str, quality_type: str, parent: Optional["QObject"] = None) -> None:
super().__init__(parent)
# The purpose of these quality groups is to group the containers that can be
# applied to a configuration, so that when a quality level is selected, the
# container can directly be applied to each stack instead of looking them up
# again.
class QualityGroup:
## Constructs a new group.
# \param name The user-visible name for the group.
# \param quality_type The quality level that each profile in this group
# has.
def __init__(self, name: str, quality_type: str) -> None:
self.name = name
self.node_for_global = None # type: Optional[ContainerNode]
self.nodes_for_extruders = {} # type: Dict[int, ContainerNode]
@ -36,7 +40,6 @@ class QualityGroup(QObject):
self.is_available = False
self.is_experimental = False
@pyqtSlot(result = str)
def getName(self) -> str:
return self.name

View file

@ -111,14 +111,7 @@ class QualityManager(QObject):
quality_group_dict = dict()
for node in nodes_to_check:
if node and node.quality_type:
# CURA-6599
# Same as QualityChangesGroup.
# For some reason, QML will get null or fail to convert type for MachineManager.activeQualityChangesGroup() to
# a QObject. Setting the object ownership to QQmlEngine.CppOwnership doesn't work, but setting the object
# parent to application seems to work.
from cura.CuraApplication import CuraApplication
quality_group = QualityGroup(node.getMetaDataEntry("name", ""), node.quality_type,
parent = CuraApplication.getInstance())
quality_group = QualityGroup(node.getMetaDataEntry("name", ""), node.quality_type)
quality_group.setGlobalNode(node)
quality_group_dict[node.quality_type] = quality_group

View file

@ -123,6 +123,14 @@ class MachineManager(QObject):
self.globalContainerChanged.connect(self.printerConnectedStatusChanged)
self.outputDevicesChanged.connect(self.printerConnectedStatusChanged)
# For updating active quality display name
self.activeQualityChanged.connect(self.activeQualityDisplayNameChanged)
self.activeIntentChanged.connect(self.activeQualityDisplayNameChanged)
self.activeQualityGroupChanged.connect(self.activeQualityDisplayNameChanged)
self.activeQualityChangesGroupChanged.connect(self.activeQualityDisplayNameChanged)
activeQualityDisplayNameChanged = pyqtSignal()
activeQualityGroupChanged = pyqtSignal()
activeQualityChangesGroupChanged = pyqtSignal()
@ -605,9 +613,10 @@ class MachineManager(QObject):
global_container_stack = cura.CuraApplication.CuraApplication.getInstance().getGlobalContainerStack()
if not global_container_stack:
return False
if not self.activeQualityGroup:
active_quality_group = self.activeQualityGroup()
if active_quality_group is None:
return False
return self.activeQualityGroup.is_available
return active_quality_group.is_available
@pyqtProperty(bool, notify = activeQualityGroupChanged)
def isActiveQualityExperimental(self) -> bool:
@ -629,16 +638,6 @@ class MachineManager(QObject):
intent_category = category
return intent_category
# Returns the human-readable name of the active intent category. If the intent category is "default", returns an
# empty string.
@pyqtProperty(str, notify = activeIntentChanged)
def activeIntentName(self) -> str:
intent_category = self.activeIntentCategory
if intent_category == "default":
intent_category = ""
intent_name = intent_category.capitalize()
return intent_name
# Provies a list of extruder positions that have a different intent from the active one.
@pyqtProperty("QStringList", notify=activeIntentChanged)
def extruderPositionsWithNonActiveIntent(self):
@ -1591,6 +1590,34 @@ class MachineManager(QObject):
if not no_dialog and self.hasUserSettings and self._application.getPreferences().getValue("cura/active_mode") == 1:
self._application.discardOrKeepProfileChanges()
# The display name of currently active quality.
# This display name is:
# - For built-in qualities (quality/intent): the quality type name, such as "Fine", "Normal", etc.
# - For custom qualities: <custom_quality_name> - <intent_name> - <quality_type_name>
# Examples:
# - "my_profile - Fine" (only based on a default quality, no intent involved)
# - "my_profile - Engineering - Fine" (based on an intent)
@pyqtProperty(str, notify = activeQualityDisplayNameChanged)
def activeQualityDisplayName(self) -> str:
global_stack = cura.CuraApplication.CuraApplication.getInstance().getGlobalContainerStack()
if global_stack is None:
return ""
# Not a custom quality
display_name = self.activeQualityOrQualityChangesName
if global_stack.qualityChanges == empty_quality_changes_container:
return display_name
# A custom quality
intent_category = self.activeIntentCategory
if intent_category != "default":
from cura.Machines.Models.IntentCategoryModel import IntentCategoryModel
intent_display_name = IntentCategoryModel.name_translation.get(intent_category, catalog.i18nc("@label", "Unknown"))
display_name += " - {intent_name}".format(intent_name = intent_display_name)
display_name += " - {quality_level_name}".format(quality_level_name = global_stack.quality.getName())
return display_name
## Change the intent category of the current printer.
#
# All extruders can change their profiles. If an intent profile is
@ -1620,13 +1647,26 @@ class MachineManager(QObject):
else: # No intent had the correct category.
extruder.intent = empty_intent_container
@pyqtProperty(QObject, fset = setQualityGroup, notify = activeQualityGroupChanged)
## Get the currently activated quality group.
#
# If no printer is added yet or the printer doesn't have quality profiles,
# this returns ``None``.
# \return The currently active quality group.
def activeQualityGroup(self) -> Optional["QualityGroup"]:
global_stack = cura.CuraApplication.CuraApplication.getInstance().getGlobalContainerStack()
if not global_stack or global_stack.quality == empty_quality_container:
return None
return ContainerTree.getInstance().getCurrentQualityGroups().get(self.activeQualityType)
## Get the name of the active quality group.
# \return The name of the active quality group.
@pyqtProperty(str, notify = activeQualityGroupChanged)
def activeQualityGroupName(self) -> str:
quality_group = self.activeQualityGroup()
if quality_group is None:
return ""
return quality_group.getName()
@pyqtSlot(QObject)
def setQualityChangesGroup(self, quality_changes_group: "QualityChangesGroup", no_dialog: bool = False) -> None:
self.blurSettings.emit()
@ -1642,7 +1682,7 @@ class MachineManager(QObject):
if self._global_container_stack is None:
return
with postponeSignals(*self._getContainerChangedSignals(), compress = CompressTechnique.CompressPerParameterValue):
self._setQualityGroup(self.activeQualityGroup)
self._setQualityGroup(self.activeQualityGroup())
for stack in [self._global_container_stack] + list(self._global_container_stack.extruders.values()):
stack.userChanges.clear()

View file

@ -15,7 +15,8 @@ variant = AA 0.4
speed_infill = =speed_print
speed_topbottom = =speed_print
speed_wall = =speed_print
speed_wall_0 = =speed_print
speed_wall_0 = =speed_wall
speed_wall_x = =speed_wall
speed_layer_0 = 20
top_bottom_thickness = =wall_thickness
wall_thickness = =line_width * 2
@ -25,8 +26,9 @@ infill_line_width = =line_width
jerk_print = 30
jerk_infill = =jerk_print
jerk_topbottom = =jerk_print
jerk_wall_0 = =jerk_print
jerk_wall_x = =jerk_print
jerk_wall = =jerk_print
jerk_wall_0 = =jerk_wall
jerk_wall_x = =jerk_wall
jerk_layer_0 = 5
line_width = =machine_nozzle_size
wall_line_width_x = =line_width

View file

@ -16,14 +16,18 @@ infill_line_width = =line_width
jerk_print = 30
jerk_infill = =jerk_print
jerk_topbottom = =jerk_print
jerk_wall_0 = =jerk_print
jerk_wall_x = =jerk_print
jerk_wall = =jerk_print
jerk_wall_0 = =jerk_wall
jerk_wall_x = =jerk_wall
jerk_layer_0 = 5
line_width = =machine_nozzle_size
speed_print = 30
speed_infill = =speed_print
speed_layer_0 = 20
speed_topbottom = =speed_print
speed_wall = =speed_print
speed_wall_0 = =speed_print
speed_wall_0 = =speed_wall
speed_wall_x = =speed_wall
top_bottom_thickness = =wall_thickness
wall_line_width_x = =line_width
wall_thickness = =line_width * 3

View file

@ -16,14 +16,18 @@ infill_line_width = =line_width
jerk_print = 30
jerk_infill = =jerk_print
jerk_topbottom = =jerk_print
jerk_wall_0 = =jerk_print
jerk_wall_x = =jerk_print
jerk_wall = =jerk_print
jerk_wall_0 = =jerk_wall
jerk_wall_x = =jerk_wall
jerk_layer_0 = 5
line_width = =machine_nozzle_size
speed_print = 30
speed_infill = =speed_print
speed_layer_0 = 20
speed_topbottom = =speed_print
speed_wall = =speed_print
speed_wall_0 = =speed_print
speed_wall_0 = =speed_wall
speed_wall_x = =speed_wall
top_bottom_thickness = =wall_thickness
wall_line_width_x = =line_width
wall_thickness = =line_width * 3

View file

@ -12,21 +12,23 @@ material = generic_pla
variant = AA 0.4
[values]
speed_infill = =speed_print
speed_topbottom = =speed_print
speed_wall = =speed_print
speed_wall_0 = =speed_wall
speed_wall_x = =speed_wall
speed_layer_0 = 20
top_bottom_thickness = =wall_thickness
wall_thickness = =line_width * 2
infill_sparse_density = 15
fill_perimeter_gaps = nowhere
infill_sparse_density = 15
infill_line_width = =line_width
jerk_print = 30
jerk_infill = =jerk_print
jerk_topbottom = =jerk_print
jerk_wall_0 = =jerk_print
jerk_wall_x = =jerk_print
jerk_wall = =jerk_print
jerk_wall_0 = =jerk_wall
jerk_wall_x = =jerk_wall
jerk_layer_0 = 5
line_width = =machine_nozzle_size
speed_infill = =speed_print
speed_topbottom = =speed_print
speed_wall = =speed_print
speed_wall_0 = =speed_print
speed_layer_0 = 20
wall_line_width_x = =line_width

View file

@ -16,14 +16,18 @@ infill_line_width = =line_width
jerk_print = 30
jerk_infill = =jerk_print
jerk_topbottom = =jerk_print
jerk_wall_0 = =jerk_print
jerk_wall_x = =jerk_print
jerk_wall = =jerk_print
jerk_wall_0 = =jerk_wall
jerk_wall_x = =jerk_wall
jerk_layer_0 = 5
line_width = =machine_nozzle_size
speed_print = 30
speed_infill = =speed_print
speed_layer_0 = 20
speed_topbottom = =speed_print
speed_wall = =speed_print
speed_wall_0 = =speed_print
speed_wall_0 = =speed_wall
speed_wall_x = =speed_wall
top_bottom_thickness = =wall_thickness
wall_line_width_x = =line_width
wall_thickness = =line_width * 3

View file

@ -16,14 +16,18 @@ infill_line_width = =line_width
jerk_print = 30
jerk_infill = =jerk_print
jerk_topbottom = =jerk_print
jerk_wall_0 = =jerk_print
jerk_wall_x = =jerk_print
jerk_wall = =jerk_print
jerk_wall_0 = =jerk_wall
jerk_wall_x = =jerk_wall
jerk_layer_0 = 5
line_width = =machine_nozzle_size
speed_print = 30
speed_infill = =speed_print
speed_layer_0 = 20
speed_topbottom = =speed_print
speed_wall = =speed_print
speed_wall_0 = =speed_print
speed_wall_0 = =speed_wall
speed_wall_x = =speed_wall
top_bottom_thickness = =wall_thickness
wall_line_width_x = =line_width
wall_thickness = =line_width * 3

View file

@ -15,7 +15,8 @@ variant = AA 0.4
speed_infill = =speed_print
speed_topbottom = =speed_print
speed_wall = =speed_print
speed_wall_0 = =speed_print
speed_wall_0 = =speed_wall
speed_wall_x = =speed_wall
speed_layer_0 = 20
top_bottom_thickness = =wall_thickness
wall_thickness = =line_width * 2
@ -25,8 +26,9 @@ infill_line_width = =line_width
jerk_print = 30
jerk_infill = =jerk_print
jerk_topbottom = =jerk_print
jerk_wall_0 = =jerk_print
jerk_wall_x = =jerk_print
jerk_wall = =jerk_print
jerk_wall_0 = =jerk_wall
jerk_wall_x = =jerk_wall
jerk_layer_0 = 5
line_width = =machine_nozzle_size
wall_line_width_x = =line_width

View file

@ -16,14 +16,18 @@ infill_line_width = =line_width
jerk_print = 30
jerk_infill = =jerk_print
jerk_topbottom = =jerk_print
jerk_wall_0 = =jerk_print
jerk_wall_x = =jerk_print
jerk_wall = =jerk_print
jerk_wall_0 = =jerk_wall
jerk_wall_x = =jerk_wall
jerk_layer_0 = 5
line_width = =machine_nozzle_size
speed_print = 30
speed_infill = =speed_print
speed_layer_0 = 20
speed_topbottom = =speed_print
speed_wall = =speed_print
speed_wall_0 = =speed_print
speed_wall_0 = =speed_wall
speed_wall_x = =speed_wall
top_bottom_thickness = =wall_thickness
wall_line_width_x = =line_width
wall_thickness = =line_width * 3

View file

@ -16,14 +16,18 @@ infill_line_width = =line_width
jerk_print = 30
jerk_infill = =jerk_print
jerk_topbottom = =jerk_print
jerk_wall_0 = =jerk_print
jerk_wall_x = =jerk_print
jerk_wall = =jerk_print
jerk_wall_0 = =jerk_wall
jerk_wall_x = =jerk_wall
jerk_layer_0 = 5
line_width = =machine_nozzle_size
speed_print = 30
speed_infill = =speed_print
speed_layer_0 = 20
speed_topbottom = =speed_print
speed_wall = =speed_print
speed_wall_0 = =speed_print
speed_wall_0 = =speed_wall
speed_wall_x = =speed_wall
top_bottom_thickness = =wall_thickness
wall_line_width_x = =line_width
wall_thickness = =line_width * 3

View file

@ -7,7 +7,7 @@ import QtQuick.Layouts 1.3
import UM 1.2 as UM
// The labelBar shows a set of labels that are evenly spaced from oneother.
// The labelBar shows a set of labels that are evenly spaced from one another.
// The first item is aligned to the left, the last is aligned to the right.
// It's intended to be used together with RadioCheckBar. As such, it needs
// to know what the used itemSize is, so it can ensure the labels are aligned correctly.

View file

@ -100,17 +100,7 @@ Item
function generateActiveQualityText()
{
var result = Cura.MachineManager.activeQualityOrQualityChangesName
// If this is a custom quality, add intent (if present) and quality it is based on
if (Cura.MachineManager.isActiveQualityCustom)
{
if (Cura.MachineManager.activeIntentName != "")
{
result += " - " + Cura.MachineManager.activeIntentName
}
result += " - " + Cura.MachineManager.activeQualityGroup.getName()
}
var result = Cura.MachineManager.activeQualityDisplayName
if (Cura.MachineManager.isActiveQualityExperimental)
{

View file

@ -20,17 +20,7 @@ RowLayout
{
if (Cura.MachineManager.activeStack)
{
var text = Cura.MachineManager.activeQualityOrQualityChangesName
// If this is a custom quality, add intent (if present) and quality it is based on
if (Cura.MachineManager.isActiveQualityCustom)
{
if (Cura.MachineManager.activeIntentName != "")
{
text += " - " + Cura.MachineManager.activeIntentName
}
text += " - " + Cura.MachineManager.activeQualityGroup.getName()
}
var text = Cura.MachineManager.activeQualityDisplayName
if (!Cura.MachineManager.hasNotSupportedQuality)
{

View file

@ -1,4 +1,4 @@
// Copyright (c) 2018 Ultimaker B.V.
// Copyright (c) 2019 Ultimaker B.V.
// Cura is released under the terms of the LGPLv3 or higher.
import QtQuick 2.10
@ -9,6 +9,7 @@ import QtQuick.Controls.Styles 1.4
import UM 1.2 as UM
import Cura 1.6 as Cura
import ".."
Item
{
id: qualityRow

View file

@ -19,7 +19,7 @@ Item
property int barSize: UM.Theme.getSize("slider_groove_radius").height
property var isCheckedFunction // Function that accepts the modelItem and returns if the item should be active.
implicitWidth: 200
implicitWidth: 200 * screenScaleFactor
implicitHeight: checkboxSize
property var dataModel: null
@ -62,7 +62,7 @@ Item
Layout.fillHeight: true
// The last item of the repeater needs to be shorter, as we don't need another part to fit
// the horizontal bar. The others should essentially not be limited.
Layout.maximumWidth: index + 1 === repeater.count ? activeComponent.width: 200000000
Layout.maximumWidth: index + 1 === repeater.count ? activeComponent.width : 200000000
property bool isEnabled: model.available
// The horizontal bar between the checkable options.

View file

@ -23,6 +23,18 @@ def container_registry():
result.findContainersMetadata = MagicMock(return_value = [metadata_dict])
return result
## Creates a machine node without anything underneath it. No sub-nodes.
#
# For testing stuff with machine nodes without testing _loadAll(). You'll need
# to add subnodes manually in your test.
@pytest.fixture
def empty_machine_node():
empty_container_registry = MagicMock()
empty_container_registry.findContainersMetadata = MagicMock(return_value = [metadata_dict]) # Still contain the MachineNode's own metadata for the constructor.
empty_container_registry.findInstanceContainersMetadata = MagicMock(return_value = [])
with patch("UM.Settings.ContainerRegistry.ContainerRegistry.getInstance", MagicMock(return_value = empty_container_registry)):
with patch("cura.Machines.MachineNode.MachineNode._loadAll", MagicMock()):
return MachineNode("machine_1")
def getMetadataEntrySideEffect(*args, **kwargs):
return metadata_dict.get(args[0])
@ -61,3 +73,99 @@ def test_metadataProperties(container_registry):
assert node.preferred_variant_name == metadata_dict["preferred_variant_name"]
assert node.preferred_material == metadata_dict["preferred_material"]
assert node.preferred_quality_type == metadata_dict["preferred_quality_type"]
## Test getting quality groups when there are quality profiles available for
# the requested configurations on two extruders.
def test_getQualityGroupsBothExtrudersAvailable(empty_machine_node):
# Prepare a tree inside the machine node.
extruder_0_node = MagicMock(quality_type = "quality_type_1")
extruder_1_node = MagicMock(quality_type = "quality_type_1") # Same quality type, so this is the one that can be returned.
empty_machine_node.variants = {
"variant_1": MagicMock(
materials = {
"material_1": MagicMock(
qualities = {
"quality_1": extruder_0_node
}
)
}
),
"variant_2": MagicMock(
materials = {
"material_2": MagicMock(
qualities = {
"quality_2": extruder_1_node
}
)
}
)
}
global_node = MagicMock(
container = MagicMock(id = "global_quality_container"), # Needs to exist, otherwise it won't add this quality type.
getMetaDataEntry = lambda _, __: "Global Quality Profile Name"
)
empty_machine_node.global_qualities = {
"quality_type_1": global_node
}
# Request the quality groups for the variants in the machine tree.
result = empty_machine_node.getQualityGroups(["variant_1", "variant_2"], ["material_1", "material_2"], [True, True])
assert "quality_type_1" in result, "This quality type was available for both extruders."
assert result["quality_type_1"].node_for_global == global_node
assert result["quality_type_1"].nodes_for_extruders[0] == extruder_0_node
assert result["quality_type_1"].nodes_for_extruders[1] == extruder_1_node
assert result["quality_type_1"].name == global_node.getMetaDataEntry("name", "Unnamed Profile")
assert result["quality_type_1"].quality_type == "quality_type_1"
## Test the "is_available" flag on quality groups.
#
# If a profile is available for a quality type on an extruder but not on all
# extruders, there should be a quality group for it but it should not be made
# available.
def test_getQualityGroupsAvailability(empty_machine_node):
# Prepare a tree inside the machine node.
extruder_0_both = MagicMock(quality_type = "quality_type_both") # This quality type is available for both extruders.
extruder_1_both = MagicMock(quality_type = "quality_type_both")
extruder_0_exclusive = MagicMock(quality_type = "quality_type_0") # These quality types are only available on one of the extruders.
extruder_1_exclusive = MagicMock(quality_type = "quality_type_1")
empty_machine_node.variants = {
"variant_1": MagicMock(
materials = {
"material_1": MagicMock(
qualities = {
"quality_0_both": extruder_0_both,
"quality_0_exclusive": extruder_0_exclusive
}
)
}
),
"variant_2": MagicMock(
materials = {
"material_2": MagicMock(
qualities = {
"quality_1_both": extruder_1_both,
"quality_1_exclusive": extruder_1_exclusive
}
)
}
)
}
global_both = MagicMock(container = MagicMock(id = "global_quality_both"), getMetaDataEntry = lambda _, __: "Global Quality Both")
global_0 = MagicMock(container = MagicMock(id = "global_quality_0"), getMetaDataEntry = lambda _, __: "Global Quality 0 Exclusive")
global_1 = MagicMock(container = MagicMock(id = "global_quality_1"), getMetaDataEntry = lambda _, __: "Global Quality 1 Exclusive")
empty_machine_node.global_qualities = {
"quality_type_both": global_both,
"quality_type_0": global_0,
"quality_type_1": global_1
}
# Request the quality groups for the variants in the machine tree.
result = empty_machine_node.getQualityGroups(["variant_1", "variant_2"], ["material_1", "material_2"], [True, True])
assert "quality_type_both" in result, "This quality type was available on both extruders."
assert result["quality_type_both"].is_available, "This quality type was available on both extruders and thus should be made available."
assert "quality_type_0" in result, "This quality type was available for one of the extruders, and so there must be a group for it (even though it's unavailable)."
assert not result["quality_type_0"].is_available, "This quality type was only available for one of the extruders and thus can't be activated."
assert "quality_type_1" in result, "This quality type was available for one of the extruders, and so there must be a group for it (even though it's unavailable)."
assert not result["quality_type_1"].is_available, "This quality type was only available for one of the extruders and thus can't be activated."

View file

@ -13,13 +13,13 @@ material_node_added_test_data = [({"type": "Not a material"}, ["material_1", "ma
({"type": "material", "base_file": "material_3"}, ["material_1", "material_2"]), # material_3 is on the "NOPE" list.
({"type": "material", "base_file": "material_4", "definition": "machine_3"}, ["material_1", "material_2"]), # Wrong machine
({"type": "material", "base_file": "material_4", "definition": "machine_1"}, ["material_1", "material_2"]), # No variant
({"type": "material", "base_file": "material_4", "definition": "machine_1", "variant": "Variant Three"}, ["material_1", "material_2"]), # Wrong variant
({"type": "material", "base_file": "material_4", "definition": "machine_1", "variant": "Variant One"}, ["material_1", "material_2", "material_4"])
({"type": "material", "base_file": "material_4", "definition": "machine_1", "variant_name": "Variant Three"}, ["material_1", "material_2"]), # Wrong variant
({"type": "material", "base_file": "material_4", "definition": "machine_1", "variant_name": "Variant One"}, ["material_1", "material_2", "material_4"])
]
material_node_update_test_data = [({"type": "material", "base_file": "material_1", "definition": "machine_1", "variant": "Variant One"}, ["material_1"], ["material_2"]),
({"type": "material", "base_file": "material_1", "definition": "fdmprinter", "variant": "Variant One"}, [], ["material_2", "material_1"]), # Too generic
({"type": "material", "base_file": "material_1", "definition": "machine_2", "variant": "Variant One"}, [], ["material_2", "material_1"]) # Wrong definition
material_node_update_test_data = [({"type": "material", "base_file": "material_1", "definition": "machine_1", "variant_name": "Variant One"}, ["material_1"], ["material_2"]),
({"type": "material", "base_file": "material_1", "definition": "fdmprinter", "variant_name": "Variant One"}, [], ["material_2", "material_1"]), # Too generic
({"type": "material", "base_file": "material_1", "definition": "machine_2", "variant_name": "Variant One"}, [], ["material_2", "material_1"]) # Wrong definition
]
metadata_dict = {}

View file

@ -56,7 +56,7 @@ def test_createMachine(application, container_registry, definition_container, gl
quality_container, intent_container, quality_changes_container):
variant_manager = MagicMock(name = "Variant Manager")
quality_manager = MagicMock(name = "Quality Manager")
global_variant_node = MagicMock( name = "global variant node")
global_variant_node = MagicMock(name = "global variant node")
global_variant_node.container = global_variant
variant_manager.getDefaultVariantNode = MagicMock(return_value = global_variant_node)
@ -98,7 +98,7 @@ def test_createExtruderStack(application, definition_container, global_variant,
application.empty_quality_container = quality_container
application.empty_intent_container = intent_container
application.empty_quality_changes_container = quality_changes_container
with patch("cura.CuraApplication.CuraApplication.getInstance", MagicMock(return_value=application)):
with patch("cura.CuraApplication.CuraApplication.getInstance", MagicMock(return_value = application)):
extruder_stack = CuraStackBuilder.createExtruderStack("Whatever", definition_container, "meh", 0, global_variant, material_instance_container, quality_container)
assert extruder_stack.variant == global_variant
assert extruder_stack.material == material_instance_container