From 3f29bce263a3ef83c770cf6c9b6a87b6f03e63f5 Mon Sep 17 00:00:00 2001 From: Ghostkeeper Date: Wed, 3 Jul 2019 16:51:47 +0200 Subject: [PATCH 01/30] List intents per category This is the naive one. We want to list the default intents multiple times, once for every quality level. Contributes to issue CURA-6597. --- cura/Machines/Models/IntentModel.py | 18 +++++++++++++++--- 1 file changed, 15 insertions(+), 3 deletions(-) diff --git a/cura/Machines/Models/IntentModel.py b/cura/Machines/Models/IntentModel.py index 3f480e2eef..26467b1d90 100644 --- a/cura/Machines/Models/IntentModel.py +++ b/cura/Machines/Models/IntentModel.py @@ -4,11 +4,10 @@ from typing import Optional from PyQt5.QtCore import QObject from UM.Qt.ListModel import ListModel -from PyQt5.QtCore import Qt +from PyQt5.QtCore import Qt, pyqtProperty, pyqtSignal from UM.Settings.ContainerRegistry import ContainerRegistry - class IntentModel(ListModel): NameRole = Qt.UserRole + 1 IdRole = Qt.UserRole + 2 @@ -21,18 +20,31 @@ class IntentModel(ListModel): self.addRoleName(self.IdRole, "id") self.addRoleName(self.ContainerRole, "container") + self._intent_category = "engineering" + ContainerRegistry.getInstance().containerAdded.connect(self._onChanged) ContainerRegistry.getInstance().containerRemoved.connect(self._onChanged) self._update() + _intent_category_changed = pyqtSignal() + + def setIntentCategory(self, new_category: str) -> None: + if self._intent_category != new_category: + self._intent_category = new_category + self._intent_category_changed.emit() + + @pyqtProperty(str, fset=setIntentCategory, notify=_intent_category_changed) + def intentCategory(self) -> str: + return self._intent_category + def _onChanged(self, container): if container.getMetaDataEntry("type") == "intent": self._update() def _update(self) -> None: new_items = [] - for container in ContainerRegistry.getInstance().findInstanceContainers(type="intent"): + for container in ContainerRegistry.getInstance().findInstanceContainers(type = "intent", intent_category = self._intent_category): new_items.append({"name": container.getName(), "id": container.getId(), "container": container}) self.setItems(new_items) From 36971f00584e655b8c251cda9e8fe38ce7037857 Mon Sep 17 00:00:00 2001 From: Ghostkeeper Date: Wed, 3 Jul 2019 16:52:33 +0200 Subject: [PATCH 02/30] Give smooth an intent and increment setting_version Smooth needs an intent because otherwise it gets the default intent. None of the default intents are allowed to have files. Contributes to issue CURA-6597. --- resources/intent/smooth.inst.cfg | 3 ++- resources/intent/strong.inst.cfg | 2 +- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/resources/intent/smooth.inst.cfg b/resources/intent/smooth.inst.cfg index e0ec3713ea..cbc95eb59a 100644 --- a/resources/intent/smooth.inst.cfg +++ b/resources/intent/smooth.inst.cfg @@ -4,8 +4,9 @@ name = Smooth (TEST INTENT) definition = fdmprinter [metadata] -setting_version = 7 +setting_version = 8 type = intent +intent_category = smooth [values] diff --git a/resources/intent/strong.inst.cfg b/resources/intent/strong.inst.cfg index 702778d598..5b26219c47 100644 --- a/resources/intent/strong.inst.cfg +++ b/resources/intent/strong.inst.cfg @@ -4,7 +4,7 @@ name = Strong (TEST INTENT) definition = fdmprinter [metadata] -setting_version = 7 +setting_version = 8 type = intent intent_category = engineering quality_type = draft From c75b83be2196857b64a453fc495249c4caaad922 Mon Sep 17 00:00:00 2001 From: Ghostkeeper Date: Thu, 4 Jul 2019 09:08:15 +0200 Subject: [PATCH 03/30] Resolve circular imports Can't import CuraApplication because we create instances of IntentManager from the IntentsModel which is created in CuraApplication. Contributes to issue CURA-6597. --- cura/Settings/IntentManager.py | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/cura/Settings/IntentManager.py b/cura/Settings/IntentManager.py index e16115ba2a..783faafed6 100644 --- a/cura/Settings/IntentManager.py +++ b/cura/Settings/IntentManager.py @@ -3,7 +3,7 @@ from PyQt5.QtCore import QObject, pyqtSignal from typing import Any, Dict, List, Set, Tuple, TYPE_CHECKING -from cura.CuraApplication import CuraApplication +import cura.CuraApplication from cura.Settings.ExtruderManager import ExtruderManager from UM.Settings.InstanceContainer import InstanceContainer @@ -20,7 +20,7 @@ class IntentManager(QObject): def __init__(self) -> None: super().__init__() - CuraApplication.getInstance().getMachineManager().activeStackChanged.connect(self.configurationChanged) + cura.CuraApplication.CuraApplication.getInstance().getMachineManager().activeStackChanged.connect(self.configurationChanged) self.configurationChanged.connect(self.selectDefaultIntent) pass @@ -42,7 +42,7 @@ class IntentManager(QObject): # \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() + registry = cura.CuraApplication.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 @@ -67,7 +67,7 @@ class IntentManager(QObject): # \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() + application = cura.CuraApplication.CuraApplication.getInstance() global_stack = application.getGlobalContainerStack() if global_stack is None: return [("default", "normal")] @@ -100,7 +100,7 @@ class IntentManager(QObject): # \return List of all categories in the current configurations of all # extruders. def currentAvailableIntentCategories(self) -> List[str]: - global_stack = CuraApplication.getInstance().getGlobalContainerStack() + global_stack = cura.CuraApplication.CuraApplication.getInstance().getGlobalContainerStack() if global_stack is None: return ["default"] current_definition_id = global_stack.definition.getMetaDataEntry("id") @@ -115,11 +115,11 @@ class IntentManager(QObject): # 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 + return cura.CuraApplication.CuraApplication.getInstance().empty_intent_container ## Apply intent on the stacks. def selectIntent(self, intent_category: str, quality_type: str) -> None: - application = CuraApplication.getInstance() + application = cura.CuraApplication.CuraApplication.getInstance() global_stack = application.getGlobalContainerStack() if global_stack is None: return From 951b91e3d85eb972c3807a80ada1271bfa3ec7b9 Mon Sep 17 00:00:00 2001 From: Ghostkeeper Date: Thu, 4 Jul 2019 09:09:22 +0200 Subject: [PATCH 04/30] Filter on 'material' metadata instead of material_id This is consistent with how the material is stored in other profiles, such as quality profiles. Contributes to issue CURA-6597. --- cura/Settings/IntentManager.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cura/Settings/IntentManager.py b/cura/Settings/IntentManager.py index 783faafed6..0067a82f41 100644 --- a/cura/Settings/IntentManager.py +++ b/cura/Settings/IntentManager.py @@ -43,7 +43,7 @@ class IntentManager(QObject): # an empty list if nothing was found. def intentMetadatas(self, definition_id: str, nozzle_name: str, material_id: str) -> List[Dict[str, Any]]: registry = cura.CuraApplication.CuraApplication.getInstance().getContainerRegistry() - return registry.findContainersMetadata(definition = definition_id, variant = nozzle_name, material_id = material_id) + return registry.findContainersMetadata(definition = definition_id, variant = nozzle_name, material = material_id) ## Collects and returns all intent categories available for the given # parameters. Note that the 'default' category is always available. From 3cce33be6f6710e7b69d4dd7cdc1dc528ef144dc Mon Sep 17 00:00:00 2001 From: Ghostkeeper Date: Thu, 4 Jul 2019 09:14:06 +0200 Subject: [PATCH 05/30] Get intents for every active extruder, not every used extruder We want the intents for basically any extruder, not just the one that would get used by a slice using the current settings for extruder_nr. Contributes to issue CURA-6597. --- cura/Settings/IntentManager.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/cura/Settings/IntentManager.py b/cura/Settings/IntentManager.py index 0067a82f41..c91f65222e 100644 --- a/cura/Settings/IntentManager.py +++ b/cura/Settings/IntentManager.py @@ -73,13 +73,13 @@ class IntentManager(QObject): 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. + # Currently _also_ inconsistent with 'currentAvailableIntentCategories', 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(): + for extruder_stack in ExtruderManager.getInstance().getActiveExtruderStacks(): 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} From 168c9db648dd4fe7780438856d68b6d6c4334211 Mon Sep 17 00:00:00 2001 From: Ghostkeeper Date: Thu, 4 Jul 2019 09:28:23 +0200 Subject: [PATCH 06/30] Code style: Space around binary operators Contributes to issue CURA-6597. --- tests/TestIntentManager.py | 28 ++++++++++++++-------------- 1 file changed, 14 insertions(+), 14 deletions(-) diff --git a/tests/TestIntentManager.py b/tests/TestIntentManager.py index c9d39f607e..06f80a2cd9 100644 --- a/tests/TestIntentManager.py +++ b/tests/TestIntentManager.py @@ -12,8 +12,8 @@ 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)): + 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 @@ -24,8 +24,8 @@ def intent_manager(application, extruder_manager, machine_manager, quality_manag 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)): + 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 @@ -65,16 +65,16 @@ def mockFindContainers(**kwargs) -> List[MockContainer]: 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) + container_registry.findContainersMetadata = MagicMock(side_effect = mockFindMetadata) + container_registry.findContainers = MagicMock(side_effect = mockFindContainers) - quality_manager.getQualityGroups = MagicMock(return_value=mocked_qualitygroup_metadata) + 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) + 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) + application.getGlobalContainerStack = MagicMock(return_value = global_stack) extruder_stack_a = MockContainer({"id": "Extruder The First"}) extruder_stack_a.variant = MockContainer({"name": "AA 0.4"}) @@ -83,15 +83,15 @@ def doSetup(application, extruder_manager, quality_manager, container_registry, 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]) + 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) + 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)): + 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" From c2b20e5cc696476cd1cca4d396ddf24fd0bee34d Mon Sep 17 00:00:00 2001 From: Ghostkeeper Date: Thu, 4 Jul 2019 09:43:25 +0200 Subject: [PATCH 07/30] Only return intents from intentMetadatas Otherwise we also get quality profiles for the same printer... Contributes to issue CURA-6597. --- cura/Settings/IntentManager.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cura/Settings/IntentManager.py b/cura/Settings/IntentManager.py index c91f65222e..c90d2cb9b0 100644 --- a/cura/Settings/IntentManager.py +++ b/cura/Settings/IntentManager.py @@ -43,7 +43,7 @@ class IntentManager(QObject): # an empty list if nothing was found. def intentMetadatas(self, definition_id: str, nozzle_name: str, material_id: str) -> List[Dict[str, Any]]: registry = cura.CuraApplication.CuraApplication.getInstance().getContainerRegistry() - return registry.findContainersMetadata(definition = definition_id, variant = nozzle_name, material = material_id) + return registry.findContainersMetadata(type = "intent", definition = definition_id, variant = nozzle_name, material = material_id) ## Collects and returns all intent categories available for the given # parameters. Note that the 'default' category is always available. From 49a6161ee8dc02993f85b4b3e611ac83fb96f6aa Mon Sep 17 00:00:00 2001 From: Ghostkeeper Date: Thu, 4 Jul 2019 11:02:49 +0200 Subject: [PATCH 08/30] Register IntentCategoryModel to be used in QML We want to be able to repeat on this model. Contributes to issue CURA-6597. --- cura/CuraApplication.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/cura/CuraApplication.py b/cura/CuraApplication.py index 28a8e12deb..f2d74a02bf 100755 --- a/cura/CuraApplication.py +++ b/cura/CuraApplication.py @@ -62,6 +62,7 @@ from cura.Arranging.ArrangeObjectsJob import ArrangeObjectsJob from cura.Arranging.ArrangeObjectsAllBuildPlatesJob import ArrangeObjectsAllBuildPlatesJob from cura.Arranging.ShapeArray import ShapeArray from cura.Machines.Models.IntentModel import IntentModel +from cura.Machines.Models.IntentCategoryModel import IntentCategoryModel from cura.Operations.SetParentOperation import SetParentOperation @@ -1070,6 +1071,7 @@ class CuraApplication(QtApplication): "CustomQualityProfilesDropDownMenuModel", self.getCustomQualityProfilesDropDownMenuModel) qmlRegisterType(NozzleModel, "Cura", 1, 0, "NozzleModel") qmlRegisterType(IntentModel, "Cura", 1, 6, "IntentModel") + qmlRegisterType(IntentCategoryModel, "Cura", 1, 6, "IntentCategoryModel") qmlRegisterType(MaterialSettingsVisibilityHandler, "Cura", 1, 0, "MaterialSettingsVisibilityHandler") qmlRegisterType(SettingVisibilityPresetsModel, "Cura", 1, 0, "SettingVisibilityPresetsModel") From 6ba70f3425dec0391e56871b4133b144854ce898 Mon Sep 17 00:00:00 2001 From: Ghostkeeper Date: Thu, 4 Jul 2019 11:04:44 +0200 Subject: [PATCH 09/30] Rewrite IntentModel to return quality types rather than actual profiles We don't want the profiles, because that'd be specific to one extruder. We want the quality types and intent categories as tuples again. Contributes to issue CURA-6597. --- cura/Machines/Models/IntentModel.py | 19 ++++++++++++------- 1 file changed, 12 insertions(+), 7 deletions(-) diff --git a/cura/Machines/Models/IntentModel.py b/cura/Machines/Models/IntentModel.py index 26467b1d90..b9839aa2ad 100644 --- a/cura/Machines/Models/IntentModel.py +++ b/cura/Machines/Models/IntentModel.py @@ -7,18 +7,18 @@ from UM.Qt.ListModel import ListModel from PyQt5.QtCore import Qt, pyqtProperty, pyqtSignal from UM.Settings.ContainerRegistry import ContainerRegistry +from cura.Settings.IntentManager import IntentManager +import cura.CuraApplication class IntentModel(ListModel): NameRole = Qt.UserRole + 1 - IdRole = Qt.UserRole + 2 - ContainerRole = Qt.UserRole + 3 + QualityTypeRole = Qt.UserRole + 2 def __init__(self, parent: Optional[QObject] = None) -> None: super().__init__(parent) self.addRoleName(self.NameRole, "name") - self.addRoleName(self.IdRole, "id") - self.addRoleName(self.ContainerRole, "container") + self.addRoleName(self.QualityTypeRole, "quality_type") self._intent_category = "engineering" @@ -34,7 +34,7 @@ class IntentModel(ListModel): self._intent_category = new_category self._intent_category_changed.emit() - @pyqtProperty(str, fset=setIntentCategory, notify=_intent_category_changed) + @pyqtProperty(str, fset = setIntentCategory, notify = _intent_category_changed) def intentCategory(self) -> str: return self._intent_category @@ -44,7 +44,12 @@ class IntentModel(ListModel): def _update(self) -> None: new_items = [] - for container in ContainerRegistry.getInstance().findInstanceContainers(type = "intent", intent_category = self._intent_category): - new_items.append({"name": container.getName(), "id": container.getId(), "container": container}) + application = cura.CuraApplication.CuraApplication.getInstance() + quality_manager = application.getQualityManager() + global_stack = application.getGlobalContainerStack() + + for intent_category, quality_type in IntentManager.getInstance().currentAvailableIntents(): + if intent_category == self._intent_category: + new_items.append({"name": quality_manager.getQualityGroups(global_stack)[quality_type].name, "quality_type": quality_type}) self.setItems(new_items) From 926df1111b25f0cb702d69ecdd19e6377fe7ef81 Mon Sep 17 00:00:00 2001 From: Ghostkeeper Date: Thu, 4 Jul 2019 11:06:47 +0200 Subject: [PATCH 10/30] Iterate over all extruder stacks rather than just the used ones Otherwise it usually only iterates over the one that the model is printing with or something. We want to iterate over all extruders that are not deactivated. Contributes to issue CURA-6597. --- cura/Settings/IntentManager.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/cura/Settings/IntentManager.py b/cura/Settings/IntentManager.py index c90d2cb9b0..841d38cded 100644 --- a/cura/Settings/IntentManager.py +++ b/cura/Settings/IntentManager.py @@ -105,7 +105,7 @@ class IntentManager(QObject): return ["default"] current_definition_id = global_stack.definition.getMetaDataEntry("id") final_intent_categories = set() # type: Set[str] - for extruder_stack in ExtruderManager.getInstance().getUsedExtruderStacks(): + for extruder_stack in ExtruderManager.getInstance().getActiveExtruderStacks(): 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)) @@ -124,7 +124,7 @@ class IntentManager(QObject): if global_stack is None: return current_definition_id = global_stack.definition.getMetaDataEntry("id") - for extruder_stack in ExtruderManager.getInstance().getUsedExtruderStacks(): + for extruder_stack in ExtruderManager.getInstance().getActiveExtruderStacks(): 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) @@ -137,5 +137,5 @@ class IntentManager(QObject): ## Selects the default intents on every extruder. def selectDefaultIntent(self) -> None: - for extruder_stack in ExtruderManager.getInstance().getUsedExtruderStacks(): + for extruder_stack in ExtruderManager.getInstance().getActiveExtruderStacks(): extruder_stack.intent = self.getDefaultIntent() From fd32abd53c7e4cd5bf4542b6901b767dd69b9771 Mon Sep 17 00:00:00 2001 From: Ghostkeeper Date: Thu, 4 Jul 2019 11:10:06 +0200 Subject: [PATCH 11/30] Add property for currently selected intent This is necessary for the interface to highlight the correct bullet or the correct menu item. Contributes to issue CURA-6597. --- cura/Settings/IntentManager.py | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/cura/Settings/IntentManager.py b/cura/Settings/IntentManager.py index 841d38cded..59cdc0115f 100644 --- a/cura/Settings/IntentManager.py +++ b/cura/Settings/IntentManager.py @@ -1,7 +1,7 @@ #Copyright (c) 2019 Ultimaker B.V. #Cura is released under the terms of the LGPLv3 or higher. -from PyQt5.QtCore import QObject, pyqtSignal +from PyQt5.QtCore import QObject, pyqtProperty, pyqtSignal, pyqtSlot from typing import Any, Dict, List, Set, Tuple, TYPE_CHECKING import cura.CuraApplication from cura.Settings.ExtruderManager import ExtruderManager @@ -31,7 +31,8 @@ class IntentManager(QObject): cls.__instance = IntentManager() return cls.__instance - configurationChanged = pyqtSignal() + configurationChanged = pyqtSignal() #Triggered when something changed in the rest of the stack. + intentCategoryChanged = pyqtSignal() #Triggered when we switch categories. ## Gets the metadata dictionaries of all intent profiles for a given # configuration. @@ -117,8 +118,14 @@ class IntentManager(QObject): def getDefaultIntent(self) -> InstanceContainer: return cura.CuraApplication.CuraApplication.getInstance().empty_intent_container + @pyqtProperty(str, notify = intentCategoryChanged) + def getCurrentIntentCategory(self) -> str: + return ExtruderManager.getInstance().getActiveExtruderStack().intent.getMetaDataEntry("intent_category") + ## Apply intent on the stacks. + @pyqtSlot(str, str) def selectIntent(self, intent_category: str, quality_type: str) -> None: + old_intent_category = self.getCurrentIntentCategory() application = cura.CuraApplication.CuraApplication.getInstance() global_stack = application.getGlobalContainerStack() if global_stack is None: @@ -134,6 +141,8 @@ class IntentManager(QObject): extruder_stack.intent = self.getDefaultIntent() application.getMachineManager().setQualityGroupByQualityType(quality_type) + if old_intent_category != intent_category: + self.intentCategoryChanged.emit() ## Selects the default intents on every extruder. def selectDefaultIntent(self) -> None: From d2daa15a13bec1d33164b0ec6201616f3ea6f8b1 Mon Sep 17 00:00:00 2001 From: Ghostkeeper Date: Thu, 4 Jul 2019 11:10:54 +0200 Subject: [PATCH 12/30] Make testing intent profiles dependent on material, printer and variant This way we can test with them (as long as you've selected ultimaker 3, AA0.4 and PLA). Contributes to issue CURA-6597. --- resources/intent/smooth.inst.cfg | 5 ++++- resources/intent/strong.inst.cfg | 4 ++-- 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/resources/intent/smooth.inst.cfg b/resources/intent/smooth.inst.cfg index cbc95eb59a..474aa05e57 100644 --- a/resources/intent/smooth.inst.cfg +++ b/resources/intent/smooth.inst.cfg @@ -1,12 +1,15 @@ [general] version = 4 name = Smooth (TEST INTENT) -definition = fdmprinter +definition = ultimaker3 [metadata] setting_version = 8 type = intent intent_category = smooth +quality_type = draft +variant = AA 0.4 +material = generic_pla [values] diff --git a/resources/intent/strong.inst.cfg b/resources/intent/strong.inst.cfg index 5b26219c47..08e568e0d7 100644 --- a/resources/intent/strong.inst.cfg +++ b/resources/intent/strong.inst.cfg @@ -1,15 +1,15 @@ [general] version = 4 name = Strong (TEST INTENT) -definition = fdmprinter +definition = ultimaker3 [metadata] setting_version = 8 type = intent intent_category = engineering quality_type = draft -material = generic_abs variant = AA 0.4 +material = generic_pla [values] From bd2237dc45371871c541a718a370eeaaa687b2f5 Mon Sep 17 00:00:00 2001 From: Ghostkeeper Date: Thu, 4 Jul 2019 11:31:59 +0200 Subject: [PATCH 13/30] Update intent categories upon adding containers or changing configuration Also upon start-up. Contributes to issue CURA-6597. --- cura/Machines/Models/IntentCategoryModel.py | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/cura/Machines/Models/IntentCategoryModel.py b/cura/Machines/Models/IntentCategoryModel.py index ac69191ca1..0766360892 100644 --- a/cura/Machines/Models/IntentCategoryModel.py +++ b/cura/Machines/Models/IntentCategoryModel.py @@ -6,6 +6,7 @@ import collections from cura.Settings.IntentManager import IntentManager from UM.Qt.ListModel import ListModel +from UM.Settings.ContainerRegistry import ContainerRegistry #To update the list if anything changes. from UM.i18n import i18nCatalog catalog = i18nCatalog("cura") @@ -34,6 +35,12 @@ class IntentCategoryModel(ListModel): self.addRoleName(self.IntentCategoryRole, "intent_category") self.addRoleName(self.WeightRole, "weight") + ContainerRegistry.getInstance().containerAdded.connect(self._onChanged) + ContainerRegistry.getInstance().containerRemoved.connect(self._onChanged) + IntentManager.getInstance().configurationChanged.connect(self._onChanged) + + self.update() + ## Updates the list of intents. def update(self) -> None: available_categories = IntentManager.getInstance().currentAvailableIntentCategories() From cf68157508f255ae9b30ef90d726ba6608d87b94 Mon Sep 17 00:00:00 2001 From: Ghostkeeper Date: Thu, 4 Jul 2019 12:29:02 +0200 Subject: [PATCH 14/30] Fix updating upon containers or configuration changing Copy-paste mistake... Contributes to issue CURA-6597. --- cura/Machines/Models/IntentCategoryModel.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/cura/Machines/Models/IntentCategoryModel.py b/cura/Machines/Models/IntentCategoryModel.py index 0766360892..83f03b158a 100644 --- a/cura/Machines/Models/IntentCategoryModel.py +++ b/cura/Machines/Models/IntentCategoryModel.py @@ -35,9 +35,9 @@ class IntentCategoryModel(ListModel): self.addRoleName(self.IntentCategoryRole, "intent_category") self.addRoleName(self.WeightRole, "weight") - ContainerRegistry.getInstance().containerAdded.connect(self._onChanged) - ContainerRegistry.getInstance().containerRemoved.connect(self._onChanged) - IntentManager.getInstance().configurationChanged.connect(self._onChanged) + ContainerRegistry.getInstance().containerAdded.connect(self.update) + ContainerRegistry.getInstance().containerRemoved.connect(self.update) + IntentManager.getInstance().configurationChanged.connect(self.update) self.update() From a6e3828eaa0f2926203c2b771f04b37354c79a5b Mon Sep 17 00:00:00 2001 From: Ghostkeeper Date: Thu, 4 Jul 2019 12:33:50 +0200 Subject: [PATCH 15/30] Efficiency: Don't update model if adding different container types In fact we might want to delay updating until after the program has started up. Contributes to issue CURA-6597. --- cura/Machines/Models/IntentCategoryModel.py | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/cura/Machines/Models/IntentCategoryModel.py b/cura/Machines/Models/IntentCategoryModel.py index 83f03b158a..c7484808ee 100644 --- a/cura/Machines/Models/IntentCategoryModel.py +++ b/cura/Machines/Models/IntentCategoryModel.py @@ -3,11 +3,15 @@ from PyQt5.QtCore import Qt import collections +from typing import TYPE_CHECKING from cura.Settings.IntentManager import IntentManager from UM.Qt.ListModel import ListModel from UM.Settings.ContainerRegistry import ContainerRegistry #To update the list if anything changes. +if TYPE_CHECKING: + from UM.Settings.ContainerRegistry import ContainerInterface + from UM.i18n import i18nCatalog catalog = i18nCatalog("cura") @@ -35,12 +39,17 @@ class IntentCategoryModel(ListModel): self.addRoleName(self.IntentCategoryRole, "intent_category") self.addRoleName(self.WeightRole, "weight") - ContainerRegistry.getInstance().containerAdded.connect(self.update) - ContainerRegistry.getInstance().containerRemoved.connect(self.update) + ContainerRegistry.getInstance().containerAdded.connect(self._onContainerChange) + ContainerRegistry.getInstance().containerRemoved.connect(self._onContainerChange) IntentManager.getInstance().configurationChanged.connect(self.update) self.update() + ## Updates the list of intents if an intent profile was added or removed. + def _onContainerChange(self, container: "ContainerInterface") -> None: + if container.getMetaDataEntry("type") == "intent": + self.update() + ## Updates the list of intents. def update(self) -> None: available_categories = IntentManager.getInstance().currentAvailableIntentCategories() From 0047874f030cbdeb479d725b2f52124a30520b66 Mon Sep 17 00:00:00 2001 From: Ghostkeeper Date: Thu, 4 Jul 2019 12:35:11 +0200 Subject: [PATCH 16/30] Get translation from list of keys rather than items Because the category is not in a list of tuples. It's just the key of the dict. Contributes to issue CURA-6597. --- cura/Machines/Models/IntentCategoryModel.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cura/Machines/Models/IntentCategoryModel.py b/cura/Machines/Models/IntentCategoryModel.py index c7484808ee..53193bd73d 100644 --- a/cura/Machines/Models/IntentCategoryModel.py +++ b/cura/Machines/Models/IntentCategoryModel.py @@ -58,6 +58,6 @@ class IntentCategoryModel(ListModel): result.append({ "name": self.name_translation.get(category, catalog.i18nc("@label", "Unknown")), "intent_category": category, - "weight": list(self.name_translation.items()).index(category) + "weight": list(self.name_translation.keys()).index(category) }) super().update(result) \ No newline at end of file From 6e373e02c0cd0b3f90f915a6082c5c139c60df32 Mon Sep 17 00:00:00 2001 From: Ghostkeeper Date: Thu, 4 Jul 2019 12:36:14 +0200 Subject: [PATCH 17/30] Update through self.setItems rather than super().update Because super().update doesn't exist in this case. Stupid. Contributes to issue CURA-6597. --- cura/Machines/Models/IntentCategoryModel.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cura/Machines/Models/IntentCategoryModel.py b/cura/Machines/Models/IntentCategoryModel.py index 53193bd73d..9a520a2d31 100644 --- a/cura/Machines/Models/IntentCategoryModel.py +++ b/cura/Machines/Models/IntentCategoryModel.py @@ -60,4 +60,4 @@ class IntentCategoryModel(ListModel): "intent_category": category, "weight": list(self.name_translation.keys()).index(category) }) - super().update(result) \ No newline at end of file + self.setItems(result) \ No newline at end of file From 45cb34c3e4b1fe9beec1ded8ee67b5a1ce714787 Mon Sep 17 00:00:00 2001 From: Ghostkeeper Date: Fri, 5 Jul 2019 11:19:16 +0200 Subject: [PATCH 18/30] Refresh list of intents upon changing category The category is changed after constructing by the QML code in order to set its property. This is now updating twice: Once for the default category and once for the final one set by QML. This is a bit inefficient. But make it work before optimising it! Contributes to issue CURA-6597. --- cura/Machines/Models/IntentModel.py | 1 + 1 file changed, 1 insertion(+) diff --git a/cura/Machines/Models/IntentModel.py b/cura/Machines/Models/IntentModel.py index b9839aa2ad..c67544e2f6 100644 --- a/cura/Machines/Models/IntentModel.py +++ b/cura/Machines/Models/IntentModel.py @@ -33,6 +33,7 @@ class IntentModel(ListModel): if self._intent_category != new_category: self._intent_category = new_category self._intent_category_changed.emit() + self._update() @pyqtProperty(str, fset = setIntentCategory, notify = _intent_category_changed) def intentCategory(self) -> str: From 32c5118ae486de22ece22da48ef00f2794569a5d Mon Sep 17 00:00:00 2001 From: Ghostkeeper Date: Fri, 5 Jul 2019 11:45:01 +0200 Subject: [PATCH 19/30] Add intents per category to the intent menu They are in the wrong order currently. The section headers all appear at the end and they are not greyed out. This must be fixed. The order might prove difficult... We'll see, but I want this locked in now because it works. Contributes to issue CURA-6597. --- resources/qml/Menus/IntentMenu.qml | 40 ++++++++++++++++++++++-------- 1 file changed, 30 insertions(+), 10 deletions(-) diff --git a/resources/qml/Menus/IntentMenu.qml b/resources/qml/Menus/IntentMenu.qml index 410ab70eb7..7e117acdb0 100644 --- a/resources/qml/Menus/IntentMenu.qml +++ b/resources/qml/Menus/IntentMenu.qml @@ -14,27 +14,47 @@ Menu property int extruderIndex: 0 - Cura.IntentModel + Cura.IntentCategoryModel { - id: intentModel + id: intentCategoryModel } Instantiator { - model: intentModel + model: intentCategoryModel - MenuItem + MenuItem //Section header. { text: model.name - checkable: true + checkable: false checked: false - Binding on checked + + property var per_category_intents: Cura.IntentModel { - when: Cura.MachineManager.activeStack != null - value: Cura.MachineManager.activeStack.intent == model.container + id: intentModel + intentCategory: model.intent_category + } + + property var intent_instantiator: Instantiator + { + model: intentModel + MenuItem + { + text: model.name + checkable: true + checked: false + Binding on checked + { + when: Cura.MachineManager.activeStack != null + value: Cura.MachineManager.activeStack.intent.metaData["intent_category"] == intentModel.intentCategory && Cura.MachineManager.activeStack.quality.metaData["quality_type"] == model.quality_type + } + exclusiveGroup: group + onTriggered: Cura.IntentManager.selectIntent(intentModel.intentCategory, model.quality_type) + } + + onObjectAdded: menu.insertItem(index, object) + onObjectRemoved: menu.removeItem(object) } - exclusiveGroup: group - onTriggered: Cura.MachineManager.activeStack.intent = model.container } onObjectAdded: menu.insertItem(index, object) From 9aeea22c738b711bc2535c6f9113ffe187291cf4 Mon Sep 17 00:00:00 2001 From: Ghostkeeper Date: Fri, 5 Jul 2019 12:05:44 +0200 Subject: [PATCH 20/30] Disable intent category headers Makes 'em look like headers. Contributes to issue CURA-6597. --- resources/qml/Menus/IntentMenu.qml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/resources/qml/Menus/IntentMenu.qml b/resources/qml/Menus/IntentMenu.qml index 7e117acdb0..8aba7cbde6 100644 --- a/resources/qml/Menus/IntentMenu.qml +++ b/resources/qml/Menus/IntentMenu.qml @@ -26,7 +26,7 @@ Menu MenuItem //Section header. { text: model.name - checkable: false + enabled: false checked: false property var per_category_intents: Cura.IntentModel From 8cea9c5b8755250490a0c8ca618b48e39972115a Mon Sep 17 00:00:00 2001 From: Ghostkeeper Date: Fri, 5 Jul 2019 13:03:20 +0200 Subject: [PATCH 21/30] Register IntentManager in QML This way we can change the intent from the interface. Contributes to issue CURA-6597. --- cura/CuraApplication.py | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/cura/CuraApplication.py b/cura/CuraApplication.py index f2d74a02bf..953336fc30 100755 --- a/cura/CuraApplication.py +++ b/cura/CuraApplication.py @@ -61,8 +61,6 @@ from cura.Arranging.Arrange import Arrange from cura.Arranging.ArrangeObjectsJob import ArrangeObjectsJob from cura.Arranging.ArrangeObjectsAllBuildPlatesJob import ArrangeObjectsAllBuildPlatesJob from cura.Arranging.ShapeArray import ShapeArray -from cura.Machines.Models.IntentModel import IntentModel -from cura.Machines.Models.IntentCategoryModel import IntentCategoryModel from cura.Operations.SetParentOperation import SetParentOperation @@ -93,6 +91,8 @@ from cura.Machines.Models.QualityProfilesDropDownMenuModel import QualityProfile from cura.Machines.Models.QualitySettingsModel import QualitySettingsModel from cura.Machines.Models.SettingVisibilityPresetsModel import SettingVisibilityPresetsModel from cura.Machines.Models.UserChangesModel import UserChangesModel +from cura.Machines.Models.IntentModel import IntentModel +from cura.Machines.Models.IntentCategoryModel import IntentCategoryModel from cura.PrinterOutput.PrinterOutputDevice import PrinterOutputDevice from cura.PrinterOutput.NetworkMJPGImage import NetworkMJPGImage @@ -105,6 +105,7 @@ from cura.Settings.ExtruderManager import ExtruderManager from cura.Settings.ExtruderStack import ExtruderStack from cura.Settings.MachineManager import MachineManager from cura.Settings.MachineNameValidator import MachineNameValidator +from cura.Settings.IntentManager import IntentManager from cura.Settings.MaterialSettingsVisibilityHandler import MaterialSettingsVisibilityHandler from cura.Settings.SettingInheritanceManager import SettingInheritanceManager from cura.Settings.SidebarCustomMenuItemsModel import SidebarCustomMenuItemsModel @@ -938,6 +939,9 @@ class CuraApplication(QtApplication): def getQualityManager(self, *args) -> "QualityManager": return self._quality_manager + def getIntentManager(self, *args) -> IntentManager: + return IntentManager.getInstance() + def getObjectsModel(self, *args): if self._object_manager is None: self._object_manager = ObjectsModel(self) @@ -1037,6 +1041,7 @@ class CuraApplication(QtApplication): qmlRegisterSingletonType(CuraSceneController, "Cura", 1, 0, "SceneController", self.getCuraSceneController) qmlRegisterSingletonType(ExtruderManager, "Cura", 1, 0, "ExtruderManager", self.getExtruderManager) qmlRegisterSingletonType(MachineManager, "Cura", 1, 0, "MachineManager", self.getMachineManager) + qmlRegisterSingletonType(IntentManager, "Cura", 1, 6, "IntentManager", self.getIntentManager) qmlRegisterSingletonType(SettingInheritanceManager, "Cura", 1, 0, "SettingInheritanceManager", self.getSettingInheritanceManager) qmlRegisterSingletonType(SimpleModeSettingsManager, "Cura", 1, 0, "SimpleModeSettingsManager", self.getSimpleModeSettingsManager) qmlRegisterSingletonType(MachineActionManager.MachineActionManager, "Cura", 1, 0, "MachineActionManager", self.getMachineActionManager) From 3729e90b249911b89d91fb8d692ca618b518ab15 Mon Sep 17 00:00:00 2001 From: Ghostkeeper Date: Fri, 5 Jul 2019 13:06:27 +0200 Subject: [PATCH 22/30] Fix getting original intent category It's now a property so it doesn't need the brackets. Contributes to issue CURA-6597. --- cura/Settings/IntentManager.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cura/Settings/IntentManager.py b/cura/Settings/IntentManager.py index 59cdc0115f..158381b189 100644 --- a/cura/Settings/IntentManager.py +++ b/cura/Settings/IntentManager.py @@ -125,7 +125,7 @@ class IntentManager(QObject): ## Apply intent on the stacks. @pyqtSlot(str, str) def selectIntent(self, intent_category: str, quality_type: str) -> None: - old_intent_category = self.getCurrentIntentCategory() + old_intent_category = self.getCurrentIntentCategory application = cura.CuraApplication.CuraApplication.getInstance() global_stack = application.getGlobalContainerStack() if global_stack is None: From 28f1e670f5623ba7f2eda6ca61726fd19963ec90 Mon Sep 17 00:00:00 2001 From: Ghostkeeper Date: Fri, 5 Jul 2019 14:20:36 +0200 Subject: [PATCH 23/30] Give special values to the intents This way we can see if the correct profile actually got loaded. Contributes to issue CURA-6597. --- resources/intent/smooth.inst.cfg | 2 +- resources/intent/strong.inst.cfg | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/resources/intent/smooth.inst.cfg b/resources/intent/smooth.inst.cfg index 474aa05e57..cfaa18c2bf 100644 --- a/resources/intent/smooth.inst.cfg +++ b/resources/intent/smooth.inst.cfg @@ -12,4 +12,4 @@ variant = AA 0.4 material = generic_pla [values] - +infill_sparse_density = 10 \ No newline at end of file diff --git a/resources/intent/strong.inst.cfg b/resources/intent/strong.inst.cfg index 08e568e0d7..e90b73d7d8 100644 --- a/resources/intent/strong.inst.cfg +++ b/resources/intent/strong.inst.cfg @@ -12,4 +12,4 @@ variant = AA 0.4 material = generic_pla [values] - +infill_sparse_density = 50 \ No newline at end of file From 07c5c4d9f02596e4eb03d85843c9638b964c65ef Mon Sep 17 00:00:00 2001 From: Ghostkeeper Date: Tue, 9 Jul 2019 10:26:49 +0200 Subject: [PATCH 24/30] Return empty model if there is no printer added yet Contributes to issue CURA-6597. --- cura/Machines/Models/IntentModel.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/cura/Machines/Models/IntentModel.py b/cura/Machines/Models/IntentModel.py index c67544e2f6..1151ff836d 100644 --- a/cura/Machines/Models/IntentModel.py +++ b/cura/Machines/Models/IntentModel.py @@ -48,6 +48,8 @@ class IntentModel(ListModel): application = cura.CuraApplication.CuraApplication.getInstance() quality_manager = application.getQualityManager() global_stack = application.getGlobalContainerStack() + if not global_stack: + self.setItems(new_items) for intent_category, quality_type in IntentManager.getInstance().currentAvailableIntents(): if intent_category == self._intent_category: From 86750c0446748c720af2d609b366404a55d2207f Mon Sep 17 00:00:00 2001 From: Ghostkeeper Date: Tue, 9 Jul 2019 10:54:47 +0200 Subject: [PATCH 25/30] Don't continue after returning empty list Oops. Shouldn't have pushed... Contributes to issue CURA-6597. --- cura/Machines/Models/IntentModel.py | 1 + 1 file changed, 1 insertion(+) diff --git a/cura/Machines/Models/IntentModel.py b/cura/Machines/Models/IntentModel.py index 1151ff836d..f4ed6e8206 100644 --- a/cura/Machines/Models/IntentModel.py +++ b/cura/Machines/Models/IntentModel.py @@ -50,6 +50,7 @@ class IntentModel(ListModel): global_stack = application.getGlobalContainerStack() if not global_stack: self.setItems(new_items) + return for intent_category, quality_type in IntentManager.getInstance().currentAvailableIntents(): if intent_category == self._intent_category: From e2fd90506a2720c02d0d344c43e88e3dc73d38ca Mon Sep 17 00:00:00 2001 From: Ghostkeeper Date: Tue, 9 Jul 2019 10:56:11 +0200 Subject: [PATCH 26/30] Include intent profiles from the default intents If we have the default intent category, list all quality types available. Contributes to issue CURA-6597. --- cura/Machines/Models/IntentModel.py | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/cura/Machines/Models/IntentModel.py b/cura/Machines/Models/IntentModel.py index f4ed6e8206..61fa14936e 100644 --- a/cura/Machines/Models/IntentModel.py +++ b/cura/Machines/Models/IntentModel.py @@ -51,9 +51,13 @@ class IntentModel(ListModel): if not global_stack: self.setItems(new_items) return + quality_groups = quality_manager.getQualityGroups(global_stack) for intent_category, quality_type in IntentManager.getInstance().currentAvailableIntents(): if intent_category == self._intent_category: - new_items.append({"name": quality_manager.getQualityGroups(global_stack)[quality_type].name, "quality_type": quality_type}) + new_items.append({"name": quality_groups[quality_type].name, "quality_type": quality_type}) + if self._intent_category == "default": #For Default we always list all quality types. We can't filter on available profiles since the empty intent is not a specific quality type. + for quality_type in quality_groups.keys(): + new_items.append({"name": quality_groups[quality_type].name, "quality_type": quality_type}) self.setItems(new_items) From 659a276f65194c5cf734a6835bd101e0cdf68389 Mon Sep 17 00:00:00 2001 From: Lipu Fei Date: Tue, 9 Jul 2019 11:29:24 +0200 Subject: [PATCH 27/30] Rename signal CURA-6597 --- cura/Machines/Models/IntentModel.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/cura/Machines/Models/IntentModel.py b/cura/Machines/Models/IntentModel.py index 61fa14936e..7b81821244 100644 --- a/cura/Machines/Models/IntentModel.py +++ b/cura/Machines/Models/IntentModel.py @@ -27,15 +27,15 @@ class IntentModel(ListModel): self._update() - _intent_category_changed = pyqtSignal() + intentCategoryChanged = pyqtSignal() def setIntentCategory(self, new_category: str) -> None: if self._intent_category != new_category: self._intent_category = new_category - self._intent_category_changed.emit() + self.intentCategoryChanged.emit() self._update() - @pyqtProperty(str, fset = setIntentCategory, notify = _intent_category_changed) + @pyqtProperty(str, fset = setIntentCategory, notify = intentCategoryChanged) def intentCategory(self) -> str: return self._intent_category From f086c1eb1199abdd4a9b41a77c732236204d5bc3 Mon Sep 17 00:00:00 2001 From: Lipu Fei Date: Tue, 9 Jul 2019 11:30:15 +0200 Subject: [PATCH 28/30] Minor cleanup changes CURA-6597 --- cura/Settings/IntentManager.py | 28 ++++++++++++++++++---------- 1 file changed, 18 insertions(+), 10 deletions(-) diff --git a/cura/Settings/IntentManager.py b/cura/Settings/IntentManager.py index 158381b189..18a7191fd7 100644 --- a/cura/Settings/IntentManager.py +++ b/cura/Settings/IntentManager.py @@ -2,9 +2,9 @@ #Cura is released under the terms of the LGPLv3 or higher. from PyQt5.QtCore import QObject, pyqtProperty, pyqtSignal, pyqtSlot -from typing import Any, Dict, List, Set, Tuple, TYPE_CHECKING +from typing import Any, Dict, List, Optional, Set, Tuple, TYPE_CHECKING import cura.CuraApplication -from cura.Settings.ExtruderManager import ExtruderManager +from cura.Settings.cura_empty_instance_containers import empty_intent_container from UM.Settings.InstanceContainer import InstanceContainer if TYPE_CHECKING: @@ -80,7 +80,7 @@ class IntentManager(QObject): final_intent_ids = set() # type: Set[str] current_definition_id = global_stack.definition.getMetaDataEntry("id") - for extruder_stack in ExtruderManager.getInstance().getActiveExtruderStacks(): + for extruder_stack in global_stack.extruderList: 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} @@ -106,7 +106,7 @@ class IntentManager(QObject): return ["default"] current_definition_id = global_stack.definition.getMetaDataEntry("id") final_intent_categories = set() # type: Set[str] - for extruder_stack in ExtruderManager.getInstance().getActiveExtruderStacks(): + for extruder_stack in global_stack.extruderList: 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)) @@ -116,22 +116,26 @@ class IntentManager(QObject): # 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 cura.CuraApplication.CuraApplication.getInstance().empty_intent_container + return empty_intent_container @pyqtProperty(str, notify = intentCategoryChanged) - def getCurrentIntentCategory(self) -> str: - return ExtruderManager.getInstance().getActiveExtruderStack().intent.getMetaDataEntry("intent_category") + def currentIntentCategory(self) -> str: + application = cura.CuraApplication.CuraApplication.getInstance() + active_extruder_stack = application.getMachineManager().activeStack + if active_extruder_stack is None: + return "" + return active_extruder_stack.intent.getMetaDataEntry("intent_category", "") ## Apply intent on the stacks. @pyqtSlot(str, str) def selectIntent(self, intent_category: str, quality_type: str) -> None: - old_intent_category = self.getCurrentIntentCategory + old_intent_category = self.currentIntentCategory application = cura.CuraApplication.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().getActiveExtruderStacks(): + for extruder_stack in global_stack.extruderList: 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) @@ -146,5 +150,9 @@ class IntentManager(QObject): ## Selects the default intents on every extruder. def selectDefaultIntent(self) -> None: - for extruder_stack in ExtruderManager.getInstance().getActiveExtruderStacks(): + application = cura.CuraApplication.CuraApplication.getInstance() + global_stack = application.getGlobalContainerStack() + if global_stack is None: + return + for extruder_stack in global_stack.extruderList: extruder_stack.intent = self.getDefaultIntent() From 8863516aa40459a20dd12f29a81a66b3f76a0aef Mon Sep 17 00:00:00 2001 From: Lipu Fei Date: Tue, 9 Jul 2019 12:53:12 +0200 Subject: [PATCH 29/30] Rename function name and fix tests CURA-6597 --- cura/Machines/Models/IntentModel.py | 2 +- cura/Settings/IntentManager.py | 2 +- tests/TestIntentManager.py | 22 +++++++++++----------- 3 files changed, 13 insertions(+), 13 deletions(-) diff --git a/cura/Machines/Models/IntentModel.py b/cura/Machines/Models/IntentModel.py index 7b81821244..87bcd08277 100644 --- a/cura/Machines/Models/IntentModel.py +++ b/cura/Machines/Models/IntentModel.py @@ -53,7 +53,7 @@ class IntentModel(ListModel): return quality_groups = quality_manager.getQualityGroups(global_stack) - for intent_category, quality_type in IntentManager.getInstance().currentAvailableIntents(): + for intent_category, quality_type in IntentManager.getInstance().getCurrentAvailableIntents(): if intent_category == self._intent_category: new_items.append({"name": quality_groups[quality_type].name, "quality_type": quality_type}) if self._intent_category == "default": #For Default we always list all quality types. We can't filter on available profiles since the empty intent is not a specific quality type. diff --git a/cura/Settings/IntentManager.py b/cura/Settings/IntentManager.py index 18a7191fd7..17e793b948 100644 --- a/cura/Settings/IntentManager.py +++ b/cura/Settings/IntentManager.py @@ -67,7 +67,7 @@ class IntentManager(QObject): # # \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]]: + def getCurrentAvailableIntents(self) -> List[Tuple[str, str]]: application = cura.CuraApplication.CuraApplication.getInstance() global_stack = application.getGlobalContainerStack() if global_stack is None: diff --git a/tests/TestIntentManager.py b/tests/TestIntentManager.py index 06f80a2cd9..337af817d1 100644 --- a/tests/TestIntentManager.py +++ b/tests/TestIntentManager.py @@ -83,6 +83,7 @@ def doSetup(application, extruder_manager, quality_manager, container_registry, extruder_stack_b.variant = MockContainer({"name": "AA 0.4"}) extruder_stack_b.material = MockContainer({"base_file": "generic_pla"}) + application.getGlobalContainerStack().extruderList = [extruder_stack_a, extruder_stack_b] extruder_manager.getUsedExtruderStacks = MagicMock(return_value = [extruder_stack_a, extruder_stack_b]) @@ -98,18 +99,17 @@ def test_intentCategories(application, intent_manager, container_registry): assert "smooth" in categories, "smooth should be in categories" -def test_currentAvailableIntents(application, extruder_manager, quality_manager, intent_manager, container_registry, global_stack): +def test_getCurrentAvailableIntents(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'. + with patch("cura.CuraApplication.CuraApplication.getInstance", MagicMock(return_value = application)): + with patch("UM.Settings.ContainerRegistry.ContainerRegistry.getInstance", MagicMock(return_value = container_registry)): + intents = intent_manager.getCurrentAvailableIntents() + 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): @@ -131,7 +131,7 @@ def test_selectIntent(application, extruder_manager, quality_manager, intent_man 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() + intents = intent_manager.getCurrentAvailableIntents() for intent, quality in intents: intent_manager.selectIntent(intent, quality) extruder_stacks = extruder_manager.getUsedExtruderStacks() From 4e0b9d7b78884b9d022c56aa299d0c7ce22dafc9 Mon Sep 17 00:00:00 2001 From: Lipu Fei Date: Tue, 9 Jul 2019 13:01:54 +0200 Subject: [PATCH 30/30] Fix typing CURA-6597 --- cura/Machines/Models/IntentModel.py | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/cura/Machines/Models/IntentModel.py b/cura/Machines/Models/IntentModel.py index 87bcd08277..275087689b 100644 --- a/cura/Machines/Models/IntentModel.py +++ b/cura/Machines/Models/IntentModel.py @@ -1,15 +1,17 @@ # Copyright (c) 2019 Ultimaker B.V. # Cura is released under the terms of the LGPLv3 or higher. -from typing import Optional -from PyQt5.QtCore import QObject -from UM.Qt.ListModel import ListModel -from PyQt5.QtCore import Qt, pyqtProperty, pyqtSignal +from typing import Optional, List, Dict, Any +from PyQt5.QtCore import Qt, QObject, pyqtProperty, pyqtSignal + +from UM.Qt.ListModel import ListModel from UM.Settings.ContainerRegistry import ContainerRegistry + from cura.Settings.IntentManager import IntentManager import cura.CuraApplication + class IntentModel(ListModel): NameRole = Qt.UserRole + 1 QualityTypeRole = Qt.UserRole + 2 @@ -44,7 +46,7 @@ class IntentModel(ListModel): self._update() def _update(self) -> None: - new_items = [] + new_items = [] # type: List[Dict[str, Any]] application = cura.CuraApplication.CuraApplication.getInstance() quality_manager = application.getQualityManager() global_stack = application.getGlobalContainerStack()