mirror of
https://git.mirrors.martin98.com/https://github.com/Ultimaker/Cura
synced 2025-08-18 06:55:55 +08:00
Merge pull request #5959 from Ultimaker/feature_intent_per_quality
Feature intent per quality
This commit is contained in:
commit
5620ee811f
@ -24,6 +24,8 @@ set(CURA_CLOUD_API_ROOT "" CACHE STRING "Alternative Cura cloud API root")
|
|||||||
set(CURA_CLOUD_API_VERSION "" CACHE STRING "Alternative Cura cloud API version")
|
set(CURA_CLOUD_API_VERSION "" CACHE STRING "Alternative Cura cloud API version")
|
||||||
|
|
||||||
configure_file(${CMAKE_SOURCE_DIR}/cura.desktop.in ${CMAKE_BINARY_DIR}/cura.desktop @ONLY)
|
configure_file(${CMAKE_SOURCE_DIR}/cura.desktop.in ${CMAKE_BINARY_DIR}/cura.desktop @ONLY)
|
||||||
|
|
||||||
|
|
||||||
configure_file(cura/CuraVersion.py.in CuraVersion.py @ONLY)
|
configure_file(cura/CuraVersion.py.in CuraVersion.py @ONLY)
|
||||||
|
|
||||||
|
|
||||||
|
@ -9,6 +9,7 @@ DEFAULT_CURA_DISPLAY_NAME = "Ultimaker Cura"
|
|||||||
DEFAULT_CURA_VERSION = "master"
|
DEFAULT_CURA_VERSION = "master"
|
||||||
DEFAULT_CURA_BUILD_TYPE = ""
|
DEFAULT_CURA_BUILD_TYPE = ""
|
||||||
DEFAULT_CURA_DEBUG_MODE = False
|
DEFAULT_CURA_DEBUG_MODE = False
|
||||||
|
DEFAULT_CURA_SDK_VERSION = "6.1.0"
|
||||||
|
|
||||||
try:
|
try:
|
||||||
from cura.CuraVersion import CuraAppName # type: ignore
|
from cura.CuraVersion import CuraAppName # type: ignore
|
||||||
@ -41,4 +42,7 @@ try:
|
|||||||
except ImportError:
|
except ImportError:
|
||||||
CuraDebugMode = DEFAULT_CURA_DEBUG_MODE
|
CuraDebugMode = DEFAULT_CURA_DEBUG_MODE
|
||||||
|
|
||||||
from cura.CuraVersion import CuraSDKVersion # type: ignore
|
# Each release has a fixed SDK version coupled with it. It doesn't make sense to make it configurable because, for
|
||||||
|
# example Cura 3.2 with SDK version 6.1 will not work. So the SDK version is hard-coded here and left out of the
|
||||||
|
# CuraVersion.py.in template.
|
||||||
|
CuraSDKVersion = "6.1.0"
|
||||||
|
@ -6,9 +6,6 @@ CuraAppDisplayName = "@CURA_APP_DISPLAY_NAME@"
|
|||||||
CuraVersion = "@CURA_VERSION@"
|
CuraVersion = "@CURA_VERSION@"
|
||||||
CuraBuildType = "@CURA_BUILDTYPE@"
|
CuraBuildType = "@CURA_BUILDTYPE@"
|
||||||
CuraDebugMode = True if "@_cura_debugmode@" == "ON" else False
|
CuraDebugMode = True if "@_cura_debugmode@" == "ON" else False
|
||||||
|
|
||||||
CuraSDKVersion = "6.1.0"
|
|
||||||
|
|
||||||
CuraCloudAPIRoot = "@CURA_CLOUD_API_ROOT@"
|
CuraCloudAPIRoot = "@CURA_CLOUD_API_ROOT@"
|
||||||
CuraCloudAPIVersion = "@CURA_CLOUD_API_VERSION@"
|
CuraCloudAPIVersion = "@CURA_CLOUD_API_VERSION@"
|
||||||
CuraCloudAccountAPIRoot = "@CURA_CLOUD_ACCOUNT_API_ROOT@"
|
CuraCloudAccountAPIRoot = "@CURA_CLOUD_ACCOUNT_API_ROOT@"
|
||||||
|
47
cura/Machines/Models/IntentCategoryModel.py
Normal file
47
cura/Machines/Models/IntentCategoryModel.py
Normal file
@ -0,0 +1,47 @@
|
|||||||
|
#Copyright (c) 2019 Ultimaker B.V.
|
||||||
|
#Cura is released under the terms of the LGPLv3 or higher.
|
||||||
|
|
||||||
|
from PyQt5.QtCore import Qt
|
||||||
|
import collections
|
||||||
|
|
||||||
|
from cura.Settings.IntentManager import IntentManager
|
||||||
|
from UM.Qt.ListModel import ListModel
|
||||||
|
|
||||||
|
from UM.i18n import i18nCatalog
|
||||||
|
catalog = i18nCatalog("cura")
|
||||||
|
|
||||||
|
## Lists the intent categories that are available for the current printer
|
||||||
|
# configuration.
|
||||||
|
class IntentCategoryModel(ListModel):
|
||||||
|
NameRole = Qt.UserRole + 1
|
||||||
|
IntentCategoryRole = Qt.UserRole + 2
|
||||||
|
WeightRole = Qt.UserRole + 3
|
||||||
|
|
||||||
|
#Translations to user-visible string. Ordered by weight.
|
||||||
|
#TODO: Create a solution for this name and weight to be used dynamically.
|
||||||
|
name_translation = collections.OrderedDict() #type: "collections.OrderedDict[str,str]"
|
||||||
|
name_translation["default"] = catalog.i18nc("@label", "Default")
|
||||||
|
name_translation["engineering"] = catalog.i18nc("@label", "Engineering")
|
||||||
|
name_translation["smooth"] = catalog.i18nc("@label", "Smooth")
|
||||||
|
|
||||||
|
## Creates a new model for a certain intent category.
|
||||||
|
# \param The category to list the intent profiles for.
|
||||||
|
def __init__(self, intent_category: str) -> None:
|
||||||
|
super().__init__()
|
||||||
|
self._intent_category = intent_category
|
||||||
|
|
||||||
|
self.addRoleName(self.NameRole, "name")
|
||||||
|
self.addRoleName(self.IntentCategoryRole, "intent_category")
|
||||||
|
self.addRoleName(self.WeightRole, "weight")
|
||||||
|
|
||||||
|
## Updates the list of intents.
|
||||||
|
def update(self) -> None:
|
||||||
|
available_categories = IntentManager.getInstance().currentAvailableIntentCategories()
|
||||||
|
result = []
|
||||||
|
for category in available_categories:
|
||||||
|
result.append({
|
||||||
|
"name": self.name_translation.get(category, catalog.i18nc("@label", "Unknown")),
|
||||||
|
"intent_category": category,
|
||||||
|
"weight": list(self.name_translation.items()).index(category)
|
||||||
|
})
|
||||||
|
super().update(result)
|
@ -194,9 +194,9 @@ class QualityManager(QObject):
|
|||||||
return quality_changes_group_dict
|
return quality_changes_group_dict
|
||||||
|
|
||||||
#
|
#
|
||||||
# Gets all quality groups for the given machine. Both available and none available ones will be included.
|
# Gets all quality groups for the given machine. Both available and unavailable ones will be included.
|
||||||
# It returns a dictionary with "quality_type"s as keys and "QualityGroup"s as values.
|
# It returns a dictionary with "quality_type"s as keys and "QualityGroup"s as values.
|
||||||
# Whether a QualityGroup is available can be unknown via the field QualityGroup.is_available.
|
# Whether a QualityGroup is available can be known via the field QualityGroup.is_available.
|
||||||
# For more details, see QualityGroup.
|
# For more details, see QualityGroup.
|
||||||
#
|
#
|
||||||
def getQualityGroups(self, machine: "GlobalStack") -> Dict[str, QualityGroup]:
|
def getQualityGroups(self, machine: "GlobalStack") -> Dict[str, QualityGroup]:
|
||||||
|
141
cura/Settings/IntentManager.py
Normal file
141
cura/Settings/IntentManager.py
Normal file
@ -0,0 +1,141 @@
|
|||||||
|
#Copyright (c) 2019 Ultimaker B.V.
|
||||||
|
#Cura is released under the terms of the LGPLv3 or higher.
|
||||||
|
|
||||||
|
from PyQt5.QtCore import QObject, pyqtSignal
|
||||||
|
from typing import Any, Dict, List, Set, Tuple, TYPE_CHECKING
|
||||||
|
from cura.CuraApplication import CuraApplication
|
||||||
|
from cura.Settings.ExtruderManager import ExtruderManager
|
||||||
|
from UM.Settings.InstanceContainer import InstanceContainer
|
||||||
|
|
||||||
|
if TYPE_CHECKING:
|
||||||
|
from UM.Settings.InstanceContainer import InstanceContainer
|
||||||
|
|
||||||
|
## Front-end for querying which intents are available for a certain
|
||||||
|
# configuration.
|
||||||
|
#
|
||||||
|
# CURRENTLY THIS CLASS CONTAINS ONLY SOME PSEUDOCODE OF WHAT WE ARE SUPPOSED
|
||||||
|
# TO IMPLEMENT.
|
||||||
|
class IntentManager(QObject):
|
||||||
|
__instance = None
|
||||||
|
|
||||||
|
def __init__(self) -> None:
|
||||||
|
super().__init__()
|
||||||
|
CuraApplication.getInstance().getMachineManager().activeStackChanged.connect(self.configurationChanged)
|
||||||
|
self.configurationChanged.connect(self.selectDefaultIntent)
|
||||||
|
pass
|
||||||
|
|
||||||
|
## This class is a singleton.
|
||||||
|
@classmethod
|
||||||
|
def getInstance(cls):
|
||||||
|
if not cls.__instance:
|
||||||
|
cls.__instance = IntentManager()
|
||||||
|
return cls.__instance
|
||||||
|
|
||||||
|
configurationChanged = pyqtSignal()
|
||||||
|
|
||||||
|
## Gets the metadata dictionaries of all intent profiles for a given
|
||||||
|
# configuration.
|
||||||
|
#
|
||||||
|
# \param definition_id ID of the printer.
|
||||||
|
# \param nozzle_name Name of the nozzle.
|
||||||
|
# \param material_id ID of the material.
|
||||||
|
# \return A list of metadata dictionaries matching the search criteria, or
|
||||||
|
# an empty list if nothing was found.
|
||||||
|
def intentMetadatas(self, definition_id: str, nozzle_name: str, material_id: str) -> List[Dict[str, Any]]:
|
||||||
|
registry = CuraApplication.getInstance().getContainerRegistry()
|
||||||
|
return registry.findContainersMetadata(definition = definition_id, variant = nozzle_name, material_id = material_id)
|
||||||
|
|
||||||
|
## Collects and returns all intent categories available for the given
|
||||||
|
# parameters. Note that the 'default' category is always available.
|
||||||
|
#
|
||||||
|
# \param definition_id ID of the printer.
|
||||||
|
# \param nozzle_name Name of the nozzle.
|
||||||
|
# \param material_id ID of the material.
|
||||||
|
# \return A set of intent category names.
|
||||||
|
def intentCategories(self, definition_id: str, nozzle_id: str, material_id: str) -> List[str]:
|
||||||
|
categories = set()
|
||||||
|
for intent in self.intentMetadatas(definition_id, nozzle_id, material_id):
|
||||||
|
categories.add(intent["intent_category"])
|
||||||
|
categories.add("default") #The "empty" intent is not an actual profile specific to the configuration but we do want it to appear in the categories list.
|
||||||
|
return list(categories)
|
||||||
|
|
||||||
|
## List of intents to be displayed in the interface.
|
||||||
|
#
|
||||||
|
# For the interface this will have to be broken up into the different
|
||||||
|
# intent categories. That is up to the model there.
|
||||||
|
#
|
||||||
|
# \return A list of tuples of intent_category and quality_type. The actual
|
||||||
|
# instance may vary per extruder.
|
||||||
|
def currentAvailableIntents(self) -> List[Tuple[str, str]]:
|
||||||
|
application = CuraApplication.getInstance()
|
||||||
|
global_stack = application.getGlobalContainerStack()
|
||||||
|
if global_stack is None:
|
||||||
|
return [("default", "normal")]
|
||||||
|
# TODO: We now do this (return a default) if the global stack is missing, but not in the code below,
|
||||||
|
# even though there should always be defaults. The problem then is what to do with the quality_types.
|
||||||
|
# Currently _also_ inconsistent with 'currentAvailableIntentCategoreis', which _does_ return default.
|
||||||
|
quality_groups = application.getQualityManager().getQualityGroups(global_stack)
|
||||||
|
available_quality_types = {quality_group.quality_type for quality_group in quality_groups.values() if quality_group.node_for_global is not None}
|
||||||
|
|
||||||
|
final_intent_ids = set() # type: Set[str]
|
||||||
|
current_definition_id = global_stack.definition.getMetaDataEntry("id")
|
||||||
|
for extruder_stack in ExtruderManager.getInstance().getUsedExtruderStacks():
|
||||||
|
nozzle_name = extruder_stack.variant.getMetaDataEntry("name")
|
||||||
|
material_id = extruder_stack.material.getMetaDataEntry("base_file")
|
||||||
|
final_intent_ids |= {metadata["id"] for metadata in self.intentMetadatas(current_definition_id, nozzle_name, material_id) if metadata["quality_type"] in available_quality_types}
|
||||||
|
|
||||||
|
result = set() # type: Set[Tuple[str, str]]
|
||||||
|
for intent_id in final_intent_ids:
|
||||||
|
intent_metadata = application.getContainerRegistry().findContainersMetadata(id = intent_id)[0]
|
||||||
|
result.add((intent_metadata["intent_category"], intent_metadata["quality_type"]))
|
||||||
|
return list(result)
|
||||||
|
|
||||||
|
## List of intent categories available in either of the extruders.
|
||||||
|
#
|
||||||
|
# This is purposefully inconsistent with the way that the quality types
|
||||||
|
# are listed. The quality types will show all quality types available in
|
||||||
|
# the printer using any configuration. This will only list the intent
|
||||||
|
# categories that are available using the current configuration (but the
|
||||||
|
# union over the extruders).
|
||||||
|
# \return List of all categories in the current configurations of all
|
||||||
|
# extruders.
|
||||||
|
def currentAvailableIntentCategories(self) -> List[str]:
|
||||||
|
global_stack = CuraApplication.getInstance().getGlobalContainerStack()
|
||||||
|
if global_stack is None:
|
||||||
|
return ["default"]
|
||||||
|
current_definition_id = global_stack.definition.getMetaDataEntry("id")
|
||||||
|
final_intent_categories = set() # type: Set[str]
|
||||||
|
for extruder_stack in ExtruderManager.getInstance().getUsedExtruderStacks():
|
||||||
|
nozzle_name = extruder_stack.variant.getMetaDataEntry("name")
|
||||||
|
material_id = extruder_stack.material.getMetaDataEntry("base_file")
|
||||||
|
final_intent_categories.update(self.intentCategories(current_definition_id, nozzle_name, material_id))
|
||||||
|
return list(final_intent_categories)
|
||||||
|
|
||||||
|
## The intent that gets selected by default when no intent is available for
|
||||||
|
# the configuration, an extruder can't match the intent that the user
|
||||||
|
# selects, or just when creating a new printer.
|
||||||
|
def getDefaultIntent(self) -> InstanceContainer:
|
||||||
|
return CuraApplication.getInstance().empty_intent_container
|
||||||
|
|
||||||
|
## Apply intent on the stacks.
|
||||||
|
def selectIntent(self, intent_category: str, quality_type: str) -> None:
|
||||||
|
application = CuraApplication.getInstance()
|
||||||
|
global_stack = application.getGlobalContainerStack()
|
||||||
|
if global_stack is None:
|
||||||
|
return
|
||||||
|
current_definition_id = global_stack.definition.getMetaDataEntry("id")
|
||||||
|
for extruder_stack in ExtruderManager.getInstance().getUsedExtruderStacks():
|
||||||
|
nozzle_name = extruder_stack.variant.getMetaDataEntry("name")
|
||||||
|
material_id = extruder_stack.material.getMetaDataEntry("base_file")
|
||||||
|
intent = application.getContainerRegistry().findContainers(definition = current_definition_id, variant = nozzle_name, material = material_id, quality_type = quality_type, intent_category = intent_category)
|
||||||
|
if intent:
|
||||||
|
extruder_stack.intent = intent[0]
|
||||||
|
else:
|
||||||
|
extruder_stack.intent = self.getDefaultIntent()
|
||||||
|
|
||||||
|
application.getMachineManager().setQualityGroupByQualityType(quality_type)
|
||||||
|
|
||||||
|
## Selects the default intents on every extruder.
|
||||||
|
def selectDefaultIntent(self) -> None:
|
||||||
|
for extruder_stack in ExtruderManager.getInstance().getUsedExtruderStacks():
|
||||||
|
extruder_stack.intent = self.getDefaultIntent()
|
@ -6,6 +6,10 @@ definition = fdmprinter
|
|||||||
[metadata]
|
[metadata]
|
||||||
setting_version = 7
|
setting_version = 7
|
||||||
type = intent
|
type = intent
|
||||||
|
intent_category = engineering
|
||||||
|
quality_type = draft
|
||||||
|
material = generic_abs
|
||||||
|
variant = AA 0.4
|
||||||
|
|
||||||
[values]
|
[values]
|
||||||
|
|
||||||
|
140
tests/TestIntentManager.py
Normal file
140
tests/TestIntentManager.py
Normal file
@ -0,0 +1,140 @@
|
|||||||
|
from unittest.mock import MagicMock, patch
|
||||||
|
|
||||||
|
import pytest
|
||||||
|
from typing import Any, Dict, List
|
||||||
|
|
||||||
|
from cura.Settings.IntentManager import IntentManager
|
||||||
|
from cura.Machines.QualityGroup import QualityGroup
|
||||||
|
from cura.Machines.QualityManager import QualityManager
|
||||||
|
|
||||||
|
from tests.Settings.MockContainer import MockContainer
|
||||||
|
|
||||||
|
@pytest.fixture()
|
||||||
|
def quality_manager(application, container_registry, global_stack) -> QualityManager:
|
||||||
|
application.getGlobalContainerStack = MagicMock(return_value = global_stack)
|
||||||
|
with patch("cura.CuraApplication.CuraApplication.getInstance", MagicMock(return_value=application)):
|
||||||
|
with patch("UM.Settings.ContainerRegistry.ContainerRegistry.getInstance", MagicMock(return_value=container_registry)):
|
||||||
|
manager = QualityManager(application)
|
||||||
|
return manager
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.fixture()
|
||||||
|
def intent_manager(application, extruder_manager, machine_manager, quality_manager, container_registry, global_stack) -> IntentManager:
|
||||||
|
application.getExtruderManager = MagicMock(return_value = extruder_manager)
|
||||||
|
application.getGlobalContainerStack = MagicMock(return_value = global_stack)
|
||||||
|
application.getMachineManager = MagicMock(return_value = machine_manager)
|
||||||
|
application.getQualityManager = MagicMock(return_value = quality_manager)
|
||||||
|
with patch("cura.CuraApplication.CuraApplication.getInstance", MagicMock(return_value=application)):
|
||||||
|
with patch("UM.Settings.ContainerRegistry.ContainerRegistry.getInstance", MagicMock(return_value=container_registry)):
|
||||||
|
manager = IntentManager()
|
||||||
|
return manager
|
||||||
|
|
||||||
|
|
||||||
|
mocked_intent_metadata = [
|
||||||
|
{"id": "um3_aa4_pla_smooth_normal", "GUID": "abcxyz", "definition": "ultimaker3", "variant": "AA 0.4",
|
||||||
|
"material_id": "generic_pla", "intent_category": "smooth", "quality_type": "normal"},
|
||||||
|
{"id": "um3_aa4_pla_strong_abnorm", "GUID": "defqrs", "definition": "ultimaker3", "variant": "AA 0.4",
|
||||||
|
"material_id": "generic_pla", "intent_category": "strong", "quality_type": "abnorm"}] # type:List[Dict[str, str]]
|
||||||
|
|
||||||
|
mocked_qualitygroup_metadata = {
|
||||||
|
"normal": QualityGroup("um3_aa4_pla_normal", "normal"),
|
||||||
|
"abnorm": QualityGroup("um3_aa4_pla_abnorm", "abnorm")} # type:Dict[str, QualityGroup]
|
||||||
|
|
||||||
|
|
||||||
|
def mockFindMetadata(**kwargs) -> List[Dict[str, Any]]:
|
||||||
|
if "id" in kwargs:
|
||||||
|
return [x for x in mocked_intent_metadata if x["id"] == kwargs["id"]]
|
||||||
|
else:
|
||||||
|
result = []
|
||||||
|
for data in mocked_intent_metadata:
|
||||||
|
should_add = True
|
||||||
|
for key, value in kwargs.items():
|
||||||
|
if key in data.keys():
|
||||||
|
should_add &= (data[key] == value)
|
||||||
|
if should_add:
|
||||||
|
result.append(data)
|
||||||
|
return result
|
||||||
|
|
||||||
|
|
||||||
|
def mockFindContainers(**kwargs) -> List[MockContainer]:
|
||||||
|
result = []
|
||||||
|
metadatas = mockFindMetadata(**kwargs)
|
||||||
|
for metadata in metadatas:
|
||||||
|
result.append(MockContainer(metadata))
|
||||||
|
return result
|
||||||
|
|
||||||
|
|
||||||
|
def doSetup(application, extruder_manager, quality_manager, container_registry, global_stack) -> None:
|
||||||
|
container_registry.findContainersMetadata = MagicMock(side_effect=mockFindMetadata)
|
||||||
|
container_registry.findContainers = MagicMock(side_effect=mockFindContainers)
|
||||||
|
|
||||||
|
quality_manager.getQualityGroups = MagicMock(return_value=mocked_qualitygroup_metadata)
|
||||||
|
for _, qualitygroup in mocked_qualitygroup_metadata.items():
|
||||||
|
qualitygroup.node_for_global = MagicMock(name="Node for global")
|
||||||
|
application.getQualityManager = MagicMock(return_value=quality_manager)
|
||||||
|
|
||||||
|
global_stack.definition = MockContainer({"id": "ultimaker3"})
|
||||||
|
application.getGlobalContainerStack = MagicMock(return_value=global_stack)
|
||||||
|
|
||||||
|
extruder_stack_a = MockContainer({"id": "Extruder The First"})
|
||||||
|
extruder_stack_a.variant = MockContainer({"name": "AA 0.4"})
|
||||||
|
extruder_stack_a.material = MockContainer({"base_file": "generic_pla"})
|
||||||
|
extruder_stack_b = MockContainer({"id": "Extruder II: Plastic Boogaloo"})
|
||||||
|
extruder_stack_b.variant = MockContainer({"name": "AA 0.4"})
|
||||||
|
extruder_stack_b.material = MockContainer({"base_file": "generic_pla"})
|
||||||
|
|
||||||
|
extruder_manager.getUsedExtruderStacks = MagicMock(return_value=[extruder_stack_a, extruder_stack_b])
|
||||||
|
|
||||||
|
|
||||||
|
def test_intentCategories(application, intent_manager, container_registry):
|
||||||
|
# Mock .findContainersMetadata so we also test .intentMetadatas (the latter is mostly a wrapper around the former).
|
||||||
|
container_registry.findContainersMetadata = MagicMock(return_value=mocked_intent_metadata)
|
||||||
|
|
||||||
|
with patch("cura.CuraApplication.CuraApplication.getInstance", MagicMock(return_value=application)):
|
||||||
|
with patch("UM.Settings.ContainerRegistry.ContainerRegistry.getInstance", MagicMock(return_value=container_registry)):
|
||||||
|
categories = intent_manager.intentCategories("ultimaker3", "AA 0.4", "generic_pla") # type:List[str]
|
||||||
|
assert "default" in categories, "default should always be in categories"
|
||||||
|
assert "strong" in categories, "strong should be in categories"
|
||||||
|
assert "smooth" in categories, "smooth should be in categories"
|
||||||
|
|
||||||
|
|
||||||
|
def test_currentAvailableIntents(application, extruder_manager, quality_manager, intent_manager, container_registry, global_stack):
|
||||||
|
doSetup(application, extruder_manager, quality_manager, container_registry, global_stack)
|
||||||
|
|
||||||
|
with patch("cura.CuraApplication.CuraApplication.getInstance", MagicMock(return_value=application)):
|
||||||
|
with patch("UM.Settings.ContainerRegistry.ContainerRegistry.getInstance", MagicMock(return_value=container_registry)):
|
||||||
|
with patch("cura.Settings.ExtruderManager.ExtruderManager.getInstance", MagicMock(return_value=extruder_manager)):
|
||||||
|
intents = intent_manager.currentAvailableIntents()
|
||||||
|
assert ("smooth", "normal") in intents
|
||||||
|
assert ("strong", "abnorm") in intents
|
||||||
|
#assert ("default", "normal") in intents # Pending to-do in 'IntentManager'.
|
||||||
|
#assert ("default", "abnorm") in intents # Pending to-do in 'IntentManager'.
|
||||||
|
assert len(intents) == 2 # Or 4? pending to-do in 'IntentManager'.
|
||||||
|
|
||||||
|
|
||||||
|
def test_currentAvailableIntentCategories(application, extruder_manager, quality_manager, intent_manager, container_registry, global_stack):
|
||||||
|
doSetup(application, extruder_manager, quality_manager, container_registry, global_stack)
|
||||||
|
|
||||||
|
with patch("cura.CuraApplication.CuraApplication.getInstance", MagicMock(return_value=application)):
|
||||||
|
with patch("UM.Settings.ContainerRegistry.ContainerRegistry.getInstance", MagicMock(return_value=container_registry)):
|
||||||
|
with patch("cura.Settings.ExtruderManager.ExtruderManager.getInstance", MagicMock(return_value=extruder_manager)):
|
||||||
|
categories = intent_manager.currentAvailableIntentCategories()
|
||||||
|
assert "default" in categories # Currently inconsistent with 'currentAvailableIntents'!
|
||||||
|
assert "smooth" in categories
|
||||||
|
assert "strong" in categories
|
||||||
|
assert len(categories) == 3
|
||||||
|
|
||||||
|
|
||||||
|
def test_selectIntent(application, extruder_manager, quality_manager, intent_manager, container_registry, global_stack):
|
||||||
|
doSetup(application, extruder_manager, quality_manager, container_registry, global_stack)
|
||||||
|
|
||||||
|
with patch("cura.CuraApplication.CuraApplication.getInstance", MagicMock(return_value=application)):
|
||||||
|
with patch("UM.Settings.ContainerRegistry.ContainerRegistry.getInstance", MagicMock(return_value=container_registry)):
|
||||||
|
with patch("cura.Settings.ExtruderManager.ExtruderManager.getInstance", MagicMock(return_value=extruder_manager)):
|
||||||
|
intents = intent_manager.currentAvailableIntents()
|
||||||
|
for intent, quality in intents:
|
||||||
|
intent_manager.selectIntent(intent, quality)
|
||||||
|
extruder_stacks = extruder_manager.getUsedExtruderStacks()
|
||||||
|
assert len(extruder_stacks) == 2
|
||||||
|
assert extruder_stacks[0].intent.getMetaDataEntry("intent_category") == intent
|
||||||
|
assert extruder_stacks[1].intent.getMetaDataEntry("intent_category") == intent
|
@ -2,42 +2,6 @@ from unittest.mock import MagicMock, patch
|
|||||||
|
|
||||||
import pytest
|
import pytest
|
||||||
|
|
||||||
from UM.Settings.ContainerRegistry import ContainerRegistry
|
|
||||||
from cura.Settings.ExtruderManager import ExtruderManager
|
|
||||||
from cura.Settings.MachineManager import MachineManager
|
|
||||||
|
|
||||||
|
|
||||||
@pytest.fixture()
|
|
||||||
def global_stack():
|
|
||||||
return MagicMock(name="Global Stack")
|
|
||||||
|
|
||||||
@pytest.fixture()
|
|
||||||
def container_registry() -> ContainerRegistry:
|
|
||||||
return MagicMock(name = "ContainerRegistry")
|
|
||||||
|
|
||||||
|
|
||||||
@pytest.fixture()
|
|
||||||
def extruder_manager(application, container_registry) -> ExtruderManager:
|
|
||||||
if ExtruderManager.getInstance() is not None:
|
|
||||||
# Reset the data
|
|
||||||
ExtruderManager._ExtruderManager__instance = None
|
|
||||||
|
|
||||||
with patch("cura.CuraApplication.CuraApplication.getInstance", MagicMock(return_value=application)):
|
|
||||||
with patch("UM.Settings.ContainerRegistry.ContainerRegistry.getInstance", MagicMock(return_value=container_registry)):
|
|
||||||
manager = ExtruderManager()
|
|
||||||
return manager
|
|
||||||
|
|
||||||
|
|
||||||
@pytest.fixture()
|
|
||||||
def machine_manager(application, extruder_manager, container_registry, global_stack) -> MachineManager:
|
|
||||||
application.getExtruderManager = MagicMock(return_value = extruder_manager)
|
|
||||||
application.getGlobalContainerStack = MagicMock(return_value = global_stack)
|
|
||||||
with patch("cura.Settings.CuraContainerRegistry.CuraContainerRegistry.getInstance", MagicMock(return_value=container_registry)):
|
|
||||||
manager = MachineManager(application)
|
|
||||||
|
|
||||||
return manager
|
|
||||||
|
|
||||||
|
|
||||||
def test_setActiveMachine(machine_manager):
|
def test_setActiveMachine(machine_manager):
|
||||||
registry = MagicMock()
|
registry = MagicMock()
|
||||||
|
|
||||||
|
@ -3,7 +3,7 @@
|
|||||||
|
|
||||||
# The purpose of this class is to create fixtures or methods that can be shared among all tests.
|
# The purpose of this class is to create fixtures or methods that can be shared among all tests.
|
||||||
|
|
||||||
import unittest.mock
|
from unittest.mock import MagicMock, patch
|
||||||
import pytest
|
import pytest
|
||||||
|
|
||||||
# Prevents error: "PyCapsule_GetPointer called with incorrect name" with conflicting SIP configurations between Arcus and PyQt: Import Arcus and Savitar first!
|
# Prevents error: "PyCapsule_GetPointer called with incorrect name" with conflicting SIP configurations between Arcus and PyQt: Import Arcus and Savitar first!
|
||||||
@ -13,16 +13,51 @@ from UM.Qt.QtApplication import QtApplication # QtApplication import is require
|
|||||||
# Even though your IDE says these files are not used, don't believe it. It's lying. They need to be there.
|
# Even though your IDE says these files are not used, don't believe it. It's lying. They need to be there.
|
||||||
|
|
||||||
from cura.CuraApplication import CuraApplication
|
from cura.CuraApplication import CuraApplication
|
||||||
|
from cura.Settings.ExtruderManager import ExtruderManager
|
||||||
|
from cura.Settings.MachineManager import MachineManager
|
||||||
from cura.UI.MachineActionManager import MachineActionManager
|
from cura.UI.MachineActionManager import MachineActionManager
|
||||||
|
from UM.Settings.ContainerRegistry import ContainerRegistry
|
||||||
|
|
||||||
# Create a CuraApplication object that will be shared among all tests. It needs to be initialized.
|
# Create a CuraApplication object that will be shared among all tests. It needs to be initialized.
|
||||||
# Since we need to use it more that once, we create the application the first time and use its instance afterwards.
|
# Since we need to use it more that once, we create the application the first time and use its instance afterwards.
|
||||||
@pytest.fixture()
|
@pytest.fixture()
|
||||||
def application() -> CuraApplication:
|
def application() -> CuraApplication:
|
||||||
app = unittest.mock.MagicMock()
|
app = MagicMock()
|
||||||
return app
|
return app
|
||||||
|
|
||||||
# Returns a MachineActionManager instance.
|
# Returns a MachineActionManager instance.
|
||||||
@pytest.fixture()
|
@pytest.fixture()
|
||||||
def machine_action_manager(application) -> MachineActionManager:
|
def machine_action_manager(application) -> MachineActionManager:
|
||||||
return MachineActionManager(application)
|
return MachineActionManager(application)
|
||||||
|
|
||||||
|
@pytest.fixture()
|
||||||
|
def global_stack():
|
||||||
|
return MagicMock(name="Global Stack")
|
||||||
|
|
||||||
|
@pytest.fixture()
|
||||||
|
def container_registry(application, global_stack) -> ContainerRegistry:
|
||||||
|
result = MagicMock()
|
||||||
|
result.findContainerStacks = MagicMock(return_value = [global_stack])
|
||||||
|
application.getContainerRegistry = MagicMock(return_value = result)
|
||||||
|
return result
|
||||||
|
|
||||||
|
@pytest.fixture()
|
||||||
|
def extruder_manager(application, container_registry) -> ExtruderManager:
|
||||||
|
if ExtruderManager.getInstance() is not None:
|
||||||
|
# Reset the data
|
||||||
|
ExtruderManager._ExtruderManager__instance = None
|
||||||
|
|
||||||
|
with patch("cura.CuraApplication.CuraApplication.getInstance", MagicMock(return_value=application)):
|
||||||
|
with patch("UM.Settings.ContainerRegistry.ContainerRegistry.getInstance", MagicMock(return_value=container_registry)):
|
||||||
|
manager = ExtruderManager()
|
||||||
|
return manager
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.fixture()
|
||||||
|
def machine_manager(application, extruder_manager, container_registry, global_stack) -> MachineManager:
|
||||||
|
application.getExtruderManager = MagicMock(return_value = extruder_manager)
|
||||||
|
application.getGlobalContainerStack = MagicMock(return_value = global_stack)
|
||||||
|
with patch("UM.Settings.ContainerRegistry.ContainerRegistry.getInstance", MagicMock(return_value=container_registry)):
|
||||||
|
manager = MachineManager(application)
|
||||||
|
|
||||||
|
return manager
|
||||||
|
Loading…
x
Reference in New Issue
Block a user