From 977beb8dbb0aa92c7dc450a2cbfbbb65ab53faf9 Mon Sep 17 00:00:00 2001 From: Ghostkeeper Date: Tue, 17 Sep 2019 08:55:29 +0200 Subject: [PATCH 01/24] Re-build container tree if has_materials changes during runtime A bit of a hack and it'll be very slow. But it should work. Right now this crashes though because it still calls the Material Manager. Contributes to issue CURA-6600. --- cura/Machines/QualityManager.py | 1 - .../MachineSettingsAction.py | 17 +++++++++++++++++ 2 files changed, 17 insertions(+), 1 deletion(-) diff --git a/cura/Machines/QualityManager.py b/cura/Machines/QualityManager.py index 4a5a4c0885..6c54a6890d 100644 --- a/cura/Machines/QualityManager.py +++ b/cura/Machines/QualityManager.py @@ -5,7 +5,6 @@ from typing import Any, Dict, List, Optional, TYPE_CHECKING from PyQt5.QtCore import QObject, pyqtSignal, pyqtSlot -from UM.Logger import Logger from UM.Util import parseBool from UM.Settings.InstanceContainer import InstanceContainer from UM.Decorators import deprecated diff --git a/plugins/MachineSettingsAction/MachineSettingsAction.py b/plugins/MachineSettingsAction/MachineSettingsAction.py index d48475b1e6..a0ce51df9b 100755 --- a/plugins/MachineSettingsAction/MachineSettingsAction.py +++ b/plugins/MachineSettingsAction/MachineSettingsAction.py @@ -11,7 +11,9 @@ from UM.Settings.ContainerRegistry import ContainerRegistry from UM.Settings.DefinitionContainer import DefinitionContainer from UM.Util import parseBool +import cura.CuraApplication # Imported like this to prevent circular dependencies. from cura.MachineAction import MachineAction +from cura.Machines.ContainerTree import ContainerTree # To re-build the machine node when hasMaterials changes. from cura.Settings.CuraStackBuilder import CuraStackBuilder from cura.Settings.cura_empty_instance_containers import isEmptyContainer @@ -41,6 +43,9 @@ class MachineSettingsAction(MachineAction): self._backend = self._application.getBackend() self.onFinished.connect(self._onFinished) + # If the g-code flavour changes between UltiGCode and another flavour, we need to update the container tree. + self._application.globalContainerStackChanged.connect(self._updateHasMaterialsInContainerTree) + # Which container index in a stack to store machine setting changes. @pyqtProperty(int, constant = True) def storeContainerIndex(self) -> int: @@ -51,6 +56,16 @@ class MachineSettingsAction(MachineAction): if isinstance(container, DefinitionContainer) and container.getMetaDataEntry("type") == "machine": self._application.getMachineActionManager().addSupportedAction(container.getId(), self.getKey()) + ## Triggered when the global container stack changes or when the g-code + # flavour setting is changed. + def _updateHasMaterialsInContainerTree(self) -> None: + global_stack = cura.CuraApplication.CuraApplication.getInstance().getGlobalContainerStack() + machine_node = ContainerTree.getInstance().machines[global_stack.definition.getId()] + + if machine_node.has_materials != parseBool(global_stack.getMetaDataEntry("has_materials")): # May have changed due to the g-code flavour. + machine_node.has_materials = parseBool(global_stack.getMetaDataEntry("has_materials")) + machine_node._loadAll() + def _reset(self): global_stack = self._application.getMachineManager().activeMachine if not global_stack: @@ -111,6 +126,8 @@ class MachineSettingsAction(MachineAction): if "has_materials" in global_stack.getMetaData(): global_stack.removeMetaDataEntry("has_materials") + self._updateHasMaterialsInContainerTree() + # set materials for position in extruder_positions: if has_materials: From eaf649023a1e73533fc49a162a7af513c11ec603 Mon Sep 17 00:00:00 2001 From: Ghostkeeper Date: Tue, 17 Sep 2019 09:23:33 +0200 Subject: [PATCH 02/24] Fix setting default material after g-code flavour changes has_materials Don't use the material manager here any more. Contributes to issue CURA-6600. --- .../MachineSettingsAction/MachineSettingsAction.py | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/plugins/MachineSettingsAction/MachineSettingsAction.py b/plugins/MachineSettingsAction/MachineSettingsAction.py index a0ce51df9b..25586ddeb0 100755 --- a/plugins/MachineSettingsAction/MachineSettingsAction.py +++ b/plugins/MachineSettingsAction/MachineSettingsAction.py @@ -113,11 +113,8 @@ class MachineSettingsAction(MachineAction): return machine_manager = self._application.getMachineManager() - material_manager = self._application.getMaterialManager() - extruder_positions = list(global_stack.extruders.keys()) has_materials = global_stack.getProperty("machine_gcode_flavor", "value") != "UltiGCode" - material_node = None if has_materials: global_stack.setMetaDataEntry("has_materials", True) else: @@ -129,10 +126,12 @@ class MachineSettingsAction(MachineAction): self._updateHasMaterialsInContainerTree() # set materials - for position in extruder_positions: - if has_materials: - material_node = material_manager.getDefaultMaterial(global_stack, position, None) - machine_manager.setMaterial(position, material_node) + machine_node = ContainerTree.getInstance().machines[global_stack.definition.getId()] + for position, extruder in enumerate(global_stack.extruderList): + #Find out what material we need to default to. + approximate_diameter = round(extruder.getProperty("material_diameter", "value")) + material_node = machine_node.variants[extruder.variant.getName()].preferredMaterial(approximate_diameter) + machine_manager.setMaterial(str(position), material_node) self._application.globalContainerStackChanged.emit() From 614c2970ea6a313ed45949d613d7f49fad1a4cc0 Mon Sep 17 00:00:00 2001 From: Ghostkeeper Date: Tue, 17 Sep 2019 15:50:38 +0200 Subject: [PATCH 03/24] Use getApproximateMaterialDiameter instead of rounded getCompatibleMaterialDiameter So we don't need to round it again. Also convert both to float to be robust against the ambiguous serialisation of floats getting in the way (e.g. '3' vs. '3.0'). Python does that sometimes. Contributes to issue CURA-6600. --- cura/Machines/MaterialManager.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/cura/Machines/MaterialManager.py b/cura/Machines/MaterialManager.py index 264f7bbd8b..fc04af3cd2 100644 --- a/cura/Machines/MaterialManager.py +++ b/cura/Machines/MaterialManager.py @@ -131,8 +131,8 @@ class MaterialManager(QObject): # Fetch the available materials (ContainerNode) for the current active machine and extruder setup. materials = self.getAvailableMaterials(machine.definition.getId(), nozzle_name) - compatible_material_diameter = str(round(extruder_stack.getCompatibleMaterialDiameter())) - result = {key: material for key, material in materials.items() if material.container and material.container.getMetaDataEntry("approximate_diameter") == compatible_material_diameter} + compatible_material_diameter = extruder_stack.getApproximateMaterialDiameter() + result = {key: material for key, material in materials.items() if material.container and float(material.container.getMetaDataEntry("approximate_diameter")) == compatible_material_diameter} return result # From 5f2e2d5320fc9c8f188b5a7d63186402c9f78721 Mon Sep 17 00:00:00 2001 From: Ghostkeeper Date: Tue, 17 Sep 2019 15:58:10 +0200 Subject: [PATCH 04/24] Use correct material diameter, rather than always 3 This function shouldn't be called any more anyway, though. Contributes to issue CURA-6600. --- cura/Machines/MaterialManager.py | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/cura/Machines/MaterialManager.py b/cura/Machines/MaterialManager.py index fc04af3cd2..0e4b60495e 100644 --- a/cura/Machines/MaterialManager.py +++ b/cura/Machines/MaterialManager.py @@ -171,9 +171,11 @@ class MaterialManager(QObject): def getMaterialNodeByType(self, global_stack: "GlobalStack", position: str, nozzle_name: str, buildplate_name: Optional[str], material_guid: str) -> Optional["MaterialNode"]: machine_definition = global_stack.definition - variant_name = global_stack.extruders[position].variant.getName() + extruder = global_stack.extruderList[int(position)] + variant_name = extruder.variant.getName() + approximate_diameter = extruder.getApproximateMaterialDiameter() - return self.getMaterialNode(machine_definition.getId(), variant_name, buildplate_name, 3, material_guid) + return self.getMaterialNode(machine_definition.getId(), variant_name, buildplate_name, approximate_diameter, material_guid) # There are 2 ways to get fallback materials; # - A fallback by type (@sa getFallbackMaterialIdByMaterialType), which adds the generic version of this material From 37d54071f031dd6727c7b4d71e4d3ff98e6b0df5 Mon Sep 17 00:00:00 2001 From: Ghostkeeper Date: Tue, 17 Sep 2019 16:35:39 +0200 Subject: [PATCH 05/24] Don't use material manager any more to sync with printers Or to change material from a base file ID. Contributes to issue CURA-6600. --- cura/Settings/MachineManager.py | 29 +++++++++++++---------------- 1 file changed, 13 insertions(+), 16 deletions(-) diff --git a/cura/Settings/MachineManager.py b/cura/Settings/MachineManager.py index a8d7379cf7..b0a6a6a5ac 100755 --- a/cura/Settings/MachineManager.py +++ b/cura/Settings/MachineManager.py @@ -26,7 +26,6 @@ import cura.CuraApplication # Imported like this to prevent circular references from cura.Machines.ContainerNode import ContainerNode from cura.Machines.ContainerTree import ContainerTree -from cura.Machines.MaterialManager import MaterialManager from cura.PrinterOutput.PrinterOutputDevice import PrinterOutputDevice, ConnectionType from cura.PrinterOutput.Models.PrinterConfigurationModel import PrinterConfigurationModel @@ -1343,6 +1342,7 @@ class MachineManager(QObject): if self._global_container_stack is None: return self.blurSettings.emit() + container_registry = CuraContainerRegistry.getInstance() with postponeSignals(*self._getContainerChangedSignals(), compress = CompressTechnique.CompressPerParameterValue): self.switchPrinterType(configuration.printerType) @@ -1379,20 +1379,18 @@ class MachineManager(QObject): else: machine_node = ContainerTree.getInstance().machines.get(self._global_container_stack.definition.getId()) variant_node = machine_node.variants.get(extruder_configuration.hotendID) - if variant_node: - self._setVariantNode(position, variant_node) - else: - self._global_container_stack.extruders[position].variant = empty_variant_container + self._setVariantNode(position, variant_node) - material_container_node = MaterialManager.getInstance().getMaterialNodeByType(self._global_container_stack, - position, - extruder_configuration.hotendID, - configuration.buildplateConfiguration, - extruder_configuration.material.guid) - if material_container_node: - self._setMaterial(position, material_container_node) - else: - self._global_container_stack.extruders[position].material = empty_material_container + # Find the material profile that the printer has stored. + # This might find one of the duplicates if the user duplicated the material to sync with. But that's okay; both have this GUID so both are correct. + approximate_diameter = int(self._global_container_stack.extruderList[int(position)].getApproximateMaterialDiameter()) + materials_with_guid = container_registry.findInstanceContainersMetadata(guid = extruder_configuration.material.guid, approximate_diameter = approximate_diameter) + material_container_node = variant_node.preferredMaterial(approximate_diameter) + if materials_with_guid: # We also have the material profile that the printer wants to share. + base_file = materials_with_guid[0]["base_file"] + material_container_node = variant_node.materials.get(base_file, default = material_container_node) # If Cura thinks that the selected material is not available for this printer, revert to the preferred material. + + self._setMaterial(position, material_container_node) self._global_container_stack.extruders[position].setEnabled(True) self.updateMaterialWithVariant(position) @@ -1440,8 +1438,7 @@ class MachineManager(QObject): extruder_stack = self._global_container_stack.extruders[position] nozzle_name = extruder_stack.variant.getName() material_diameter = extruder_stack.getApproximateMaterialDiameter() - material_node = MaterialManager.getInstance().getMaterialNode(machine_definition_id, nozzle_name, buildplate_name, - material_diameter, root_material_id) + material_node = ContainerTree.getInstance().machines[machine_definition_id].variants[nozzle_name].materials[root_material_id] self.setMaterial(position, material_node) ## Global_stack: if you want to provide your own global_stack instead of the current active one From 5f4051ab5c62d19313e29c8207a9ebaf6e8b2192 Mon Sep 17 00:00:00 2001 From: Ghostkeeper Date: Tue, 17 Sep 2019 16:41:32 +0200 Subject: [PATCH 06/24] Use getApproximateMaterialDiameter instead of rounded getCompatibleMaterialDiameter There was a function to round it for us already. Contributes to issue CURA-6600. --- cura/Machines/Models/BaseMaterialsModel.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/cura/Machines/Models/BaseMaterialsModel.py b/cura/Machines/Models/BaseMaterialsModel.py index 66718e8e4f..e2c43ed883 100644 --- a/cura/Machines/Models/BaseMaterialsModel.py +++ b/cura/Machines/Models/BaseMaterialsModel.py @@ -127,8 +127,8 @@ class BaseMaterialsModel(ListModel): return nozzle_name = extruder_stack.variant.getName() materials = ContainerTree.getInstance().machines[global_stack.definition.getId()].variants[nozzle_name].materials - compatible_material_diameter = str(round(extruder_stack.getCompatibleMaterialDiameter())) - self._available_materials = {key: material for key, material in materials.items() if material.container.getMetaDataEntry("approximate_diameter") == compatible_material_diameter} + approximate_material_diameter = extruder_stack.getApproximateMaterialDiameter() + self._available_materials = {key: material for key, material in materials.items() if float(material.container.getMetaDataEntry("approximate_diameter")) == approximate_material_diameter} ## This method is used by all material models in the beginning of the # _update() method in order to prevent errors. It's the same in all models From 3712f9c1f8a8366fac7b344dcae388075d1ce4ed Mon Sep 17 00:00:00 2001 From: Ghostkeeper Date: Tue, 17 Sep 2019 16:56:00 +0200 Subject: [PATCH 07/24] Correct parameter name It's the base file, not the ID. Contributes to issue CURA-6600. --- cura/Settings/IntentManager.py | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/cura/Settings/IntentManager.py b/cura/Settings/IntentManager.py index 251cf0aed8..8de660145e 100644 --- a/cura/Settings/IntentManager.py +++ b/cura/Settings/IntentManager.py @@ -13,9 +13,6 @@ if TYPE_CHECKING: ## 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 @@ -43,9 +40,9 @@ class IntentManager(QObject): # \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]]: + def intentMetadatas(self, definition_id: str, nozzle_name: str, material_base_file: str) -> List[Dict[str, Any]]: registry = cura.CuraApplication.CuraApplication.getInstance().getContainerRegistry() - return registry.findContainersMetadata(type = "intent", definition = definition_id, variant = nozzle_name, material = material_id) + return registry.findContainersMetadata(type = "intent", definition = definition_id, variant = nozzle_name, material = material_base_file) ## Collects and returns all intent categories available for the given # parameters. Note that the 'default' category is always available. From fc679758ef22031ab532a6461aaf9984d812dd1a Mon Sep 17 00:00:00 2001 From: Ghostkeeper Date: Tue, 17 Sep 2019 16:57:16 +0200 Subject: [PATCH 08/24] Optimise getting intent categories It's in the container tree, so there's no need for separate queries to the container registry. Contributes to issue CURA-6600. --- cura/Settings/IntentManager.py | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/cura/Settings/IntentManager.py b/cura/Settings/IntentManager.py index 8de660145e..89df530f6a 100644 --- a/cura/Settings/IntentManager.py +++ b/cura/Settings/IntentManager.py @@ -37,12 +37,16 @@ class IntentManager(QObject): # # \param definition_id ID of the printer. # \param nozzle_name Name of the nozzle. - # \param material_id ID of the material. + # \param material_base_file The base_file 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_base_file: str) -> List[Dict[str, Any]]: - registry = cura.CuraApplication.CuraApplication.getInstance().getContainerRegistry() - return registry.findContainersMetadata(type = "intent", definition = definition_id, variant = nozzle_name, material = material_base_file) + material_node = ContainerTree.getInstance().machines[definition_id].variants[nozzle_name].materials[material_base_file] + intent_metadatas = [] + for quality_node in material_node.qualities.values(): + for intent_node in quality_node.intents.values(): + intent_metadatas.append(intent_node.getMetadata()) + return intent_metadatas ## Collects and returns all intent categories available for the given # parameters. Note that the 'default' category is always available. From 80e79f6e7ea13012474316eb2eaab420bf7e394b Mon Sep 17 00:00:00 2001 From: Ghostkeeper Date: Tue, 17 Sep 2019 16:58:12 +0200 Subject: [PATCH 09/24] Remove TODO Was done in previous commit, but I already pushed so no more --amend now. Contributes to issue CURA-6600. --- cura/Settings/IntentManager.py | 1 - 1 file changed, 1 deletion(-) diff --git a/cura/Settings/IntentManager.py b/cura/Settings/IntentManager.py index 89df530f6a..71f5e3705a 100644 --- a/cura/Settings/IntentManager.py +++ b/cura/Settings/IntentManager.py @@ -78,7 +78,6 @@ class IntentManager(QObject): # even though there should always be defaults. The problem then is what to do with the quality_types. # Currently _also_ inconsistent with 'currentAvailableIntentCategories', which _does_ return default. quality_groups = ContainerTree.getInstance().getCurrentQualityGroups() - # TODO: These quality nodes in that tree already contain the intent nodes. We can optimise this. 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] From 963f5e6dd73d780ce19f5cc02a0d22f22ce696aa Mon Sep 17 00:00:00 2001 From: Ghostkeeper Date: Tue, 17 Sep 2019 17:03:05 +0200 Subject: [PATCH 10/24] Use getApproximateMaterialDiameter rather than getCompatibleMaterialDiameter Should we deprecate getCompatibleMaterialDiameter? I don't think the un-rounded diameter should ever be used for compatibility checks. Contributes to issue CURA-6600. --- cura/Settings/MachineManager.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/cura/Settings/MachineManager.py b/cura/Settings/MachineManager.py index b0a6a6a5ac..ac44163898 100755 --- a/cura/Settings/MachineManager.py +++ b/cura/Settings/MachineManager.py @@ -1300,8 +1300,7 @@ class MachineManager(QObject): self._setMaterial(position_item, new_material) else: # The current material is not available, find the preferred one. - material_diameter = self._global_container_stack.extruders[position].getCompatibleMaterialDiameter() - approximate_material_diameter = round(material_diameter) + approximate_material_diameter = int(self._global_container_stack.extruderList[int(position)].getApproximateMaterialDiameter()) material_node = nozzle_node.preferredMaterial(approximate_material_diameter) self._setMaterial(position_item, material_node) From 0eb3c5c0d63d61c390c450a1b066fd2821277df4 Mon Sep 17 00:00:00 2001 From: Ghostkeeper Date: Tue, 17 Sep 2019 17:50:38 +0200 Subject: [PATCH 11/24] Refer material manager functions through to material management model That's where the materials are duplicated now. So we only maintain one implementation of that. Contributes to issue CURA-6600. --- cura/Machines/MaterialManager.py | 87 +++++-------------- .../Models/MaterialManagementModel.py | 28 ++++-- 2 files changed, 40 insertions(+), 75 deletions(-) diff --git a/cura/Machines/MaterialManager.py b/cura/Machines/MaterialManager.py index 0e4b60495e..08f1bdcba5 100644 --- a/cura/Machines/MaterialManager.py +++ b/cura/Machines/MaterialManager.py @@ -289,74 +289,27 @@ class MaterialManager(QObject): if root_material_id is not None: self.removeMaterialByRootId(root_material_id) - def duplicateMaterialByRootId(self, root_material_id: str, new_base_id: Optional[str] = None, - new_metadata: Optional[Dict[str, Any]] = None) -> Optional[str]: - container_registry = CuraContainerRegistry.getInstance() - results = container_registry.findContainers(id=root_material_id) - - if not results: - Logger.log("i", "Unable to duplicate the material with id %s, because it doesn't exist.", root_material_id) - return None - - base_container = results[0] - - # Ensure all settings are saved. - cura.CuraApplication.CuraApplication.getInstance().saveSettings() - - # Create a new ID & container to hold the data. - new_containers = [] - if new_base_id is None: - new_base_id = container_registry.uniqueName(base_container.getId()) - new_base_container = copy.deepcopy(base_container) - new_base_container.getMetaData()["id"] = new_base_id - new_base_container.getMetaData()["base_file"] = new_base_id - if new_metadata is not None: - for key, value in new_metadata.items(): - new_base_container.getMetaData()[key] = value - new_containers.append(new_base_container) - - # Clone all of them. - for container_to_copy in container_registry.findContainers(base_file=root_material_id): - if container_to_copy.getId() == root_material_id: - continue # We already have that one, skip it - new_id = new_base_id - if container_to_copy.getMetaDataEntry("definition") != "fdmprinter": - new_id += "_" + container_to_copy.getMetaDataEntry("definition") - if container_to_copy.getMetaDataEntry("variant_name"): - nozzle_name = container_to_copy.getMetaDataEntry("variant_name") - new_id += "_" + nozzle_name.replace(" ", "_") - - new_container = copy.deepcopy(container_to_copy) - new_container.getMetaData()["id"] = new_id - new_container.getMetaData()["base_file"] = new_base_id - if new_metadata is not None: - for key, value in new_metadata.items(): - new_container.getMetaData()[key] = value - new_containers.append(new_container) - - for container_to_add in new_containers: - container_to_add.setDirty(True) - container_registry.addContainer(container_to_add) - - # if the duplicated material was favorite then the new material should also be added to favorite. - if root_material_id in self.getFavorites(): - cura.CuraApplication.CuraApplication.getInstance().getMaterialManagementModel().addFavorite(new_base_id) - - return new_base_id - - # - # Creates a duplicate of a material, which has the same GUID and base_file metadata. - # Returns the root material ID of the duplicated material if successful. - # - @pyqtSlot("QVariant", result = str) - def duplicateMaterial(self, material_node: MaterialNode, new_base_id: Optional[str] = None, - new_metadata: Optional[Dict[str, Any]] = None) -> str: - if material_node.container is None: - Logger.log("e", "Material node {0} doesn't have container.".format(material_node.container_id)) + def duplicateMaterialByRootId(self, root_material_id: str, new_base_id: Optional[str] = None, new_metadata: Optional[Dict[str, Any]] = None) -> Optional[str]: + result = cura.CuraApplication.CuraApplication.getInstance().getMaterialManagementModel().duplicateMaterialByBaseFile(root_material_id, new_base_id, new_metadata) + if result is None: return "ERROR" - root_material_id = cast(str, material_node.container.getMetaDataEntry("base_file", "")) - new_material_id = self.duplicateMaterialByRootId(root_material_id, new_base_id, new_metadata) - return new_material_id if new_material_id is not None else "ERROR" + return result + + ## Creates a duplicate of a material with the same GUID and base_file + # metadata. + # \param material_node The node representing the material to duplicate. + # \param new_base_id A new material ID for the base material. The IDs of + # the submaterials will be based off this one. If not provided, a material + # ID will be generated automatically. + # \param new_metadata Metadata for the new material. If not provided, this + # will be duplicated from the original material. + # \return The root material ID of the duplicate material. + @pyqtSlot("QVariant", result = str) + def duplicateMaterial(self, material_node: MaterialNode, new_base_id: Optional[str] = None, new_metadata: Optional[Dict[str, Any]] = None) -> str: + result = cura.CuraApplication.CuraApplication.getInstance().getMaterialManagementModel().duplicateMaterial(material_node, new_base_id, new_metadata) + if result is None: + return "ERROR" + return result # Create a new material by cloning Generic PLA for the current material diameter and generate a new GUID. # Returns the ID of the newly created material. diff --git a/cura/Machines/Models/MaterialManagementModel.py b/cura/Machines/Models/MaterialManagementModel.py index f9af587293..a0b61e0b9b 100644 --- a/cura/Machines/Models/MaterialManagementModel.py +++ b/cura/Machines/Models/MaterialManagementModel.py @@ -73,20 +73,19 @@ class MaterialManagementModel(QObject): ## Creates a duplicate of a material with the same GUID and base_file # metadata. - # \param material_node The node representing the material to duplicate. + # \param base_file: The base file of the material to duplicate. # \param new_base_id A new material ID for the base material. The IDs of # the submaterials will be based off this one. If not provided, a material # ID will be generated automatically. # \param new_metadata Metadata for the new material. If not provided, this # will be duplicated from the original material. # \return The root material ID of the duplicate material. - @pyqtSlot("QVariant", result = str) - def duplicateMaterial(self, material_node: "MaterialNode", new_base_id: Optional[str] = None, new_metadata: Dict[str, Any] = None) -> Optional[str]: + def duplicateMaterialByBaseFile(self, base_file: str, new_base_id: Optional[str] = None, new_metadata: Dict[str, Any] = None) -> Optional[str]: container_registry = CuraContainerRegistry.getInstance() - root_materials = container_registry.findContainers(id = material_node.base_file) + root_materials = container_registry.findContainers(id = base_file) if not root_materials: - Logger.log("i", "Unable to duplicate the root material with ID {root_id}, because it doesn't exist.".format(root_id = material_node.base_file)) + Logger.log("i", "Unable to duplicate the root material with ID {root_id}, because it doesn't exist.".format(root_id = base_file)) return None root_material = root_materials[0] @@ -105,8 +104,8 @@ class MaterialManagementModel(QObject): new_containers = [new_root_material] # Clone all submaterials. - for container_to_copy in container_registry.findInstanceContainers(base_file = material_node.base_file): - if container_to_copy.getId() == material_node.base_file: + for container_to_copy in container_registry.findInstanceContainers(base_file = base_file): + if container_to_copy.getId() == base_file: continue # We already have that one. Skip it. new_id = new_base_id definition = container_to_copy.getMetaDataEntry("definition") @@ -129,12 +128,25 @@ class MaterialManagementModel(QObject): # If the duplicated material was favorite then the new material should also be added to the favorites. favorites_set = set(application.getPreferences().getValue("cura/favorite_materials").split(";")) - if material_node.base_file in favorites_set: + if base_file in favorites_set: favorites_set.add(new_base_id) application.getPreferences().setValue("cura/favorite_materials", ";".join(favorites_set)) return new_base_id + ## Creates a duplicate of a material with the same GUID and base_file + # metadata. + # \param material_node The node representing the material to duplicate. + # \param new_base_id A new material ID for the base material. The IDs of + # the submaterials will be based off this one. If not provided, a material + # ID will be generated automatically. + # \param new_metadata Metadata for the new material. If not provided, this + # will be duplicated from the original material. + # \return The root material ID of the duplicate material. + @pyqtSlot("QVariant", result = str) + def duplicateMaterial(self, material_node: "MaterialNode", new_base_id: Optional[str] = None, new_metadata: Dict[str, Any] = None) -> Optional[str]: + return self.duplicateMaterialByBaseFile(material_node.base_file, new_base_id, new_metadata) + ## Create a new material by cloning the preferred material for the current # material diameter and generate a new GUID. # From 9392a3553c08b576f0e5c513cd8e9605f0f9c8c4 Mon Sep 17 00:00:00 2001 From: Ghostkeeper Date: Tue, 17 Sep 2019 17:54:26 +0200 Subject: [PATCH 12/24] Use implementation from MaterialManagementModel The material manager is deprecated now. Contributes to issue CURA-6600. --- cura/Machines/MaterialManager.py | 38 +++++++------------------------- 1 file changed, 8 insertions(+), 30 deletions(-) diff --git a/cura/Machines/MaterialManager.py b/cura/Machines/MaterialManager.py index 08f1bdcba5..831605e8d2 100644 --- a/cura/Machines/MaterialManager.py +++ b/cura/Machines/MaterialManager.py @@ -311,38 +311,16 @@ class MaterialManager(QObject): return "ERROR" return result - # Create a new material by cloning Generic PLA for the current material diameter and generate a new GUID. - # Returns the ID of the newly created material. + ## Create a new material by cloning the preferred material for the current + # material diameter and generate a new GUID. + # + # The material type is explicitly left to be the one from the preferred + # material, since this allows the user to still have SOME profiles to work + # with. + # \return The ID of the newly created material. @pyqtSlot(result = str) def createMaterial(self) -> str: - from UM.i18n import i18nCatalog - catalog = i18nCatalog("cura") - # Ensure all settings are saved. - application = cura.CuraApplication.CuraApplication.getInstance() - application.saveSettings() - - machine_manager = application.getMachineManager() - extruder_stack = machine_manager.activeStack - - global_stack = application.getGlobalContainerStack() - if global_stack is None: - Logger.log("e", "Global stack not present!") - return "ERROR" - machine_definition = global_stack.definition - root_material_id = machine_definition.getMetaDataEntry("preferred_material", default = "generic_pla") - - approximate_diameter = str(extruder_stack.approximateMaterialDiameter) - root_material_id = self.getRootMaterialIDForDiameter(root_material_id, approximate_diameter) - - # Create a new ID & container to hold the data. - new_id = CuraContainerRegistry.getInstance().uniqueName("custom_material") - new_metadata = {"name": catalog.i18nc("@label", "Custom Material"), - "brand": catalog.i18nc("@label", "Custom"), - "GUID": str(uuid.uuid4()), - } - - self.duplicateMaterialByRootId(root_material_id, new_base_id = new_id, new_metadata = new_metadata) - return new_id + return cura.CuraApplication.CuraApplication.getMaterialManagementModel().createMaterial() @pyqtSlot(str) def addFavorite(self, root_material_id: str) -> None: From 8710bb77a7db2fa2a630b9bc966b4aa83c0c481d Mon Sep 17 00:00:00 2001 From: Ghostkeeper Date: Tue, 17 Sep 2019 17:57:32 +0200 Subject: [PATCH 13/24] Use MaterialManagementModel to rename materials It's the replacement for the deprecation. Contributes to issue CURA-6600. --- cura/Machines/MaterialManager.py | 14 ++++---------- 1 file changed, 4 insertions(+), 10 deletions(-) diff --git a/cura/Machines/MaterialManager.py b/cura/Machines/MaterialManager.py index 831605e8d2..a5cefcb8f4 100644 --- a/cura/Machines/MaterialManager.py +++ b/cura/Machines/MaterialManager.py @@ -268,18 +268,12 @@ class MaterialManager(QObject): return False return True + ## Change the user-visible name of a material. + # \param material_node The ContainerTree node of the material to rename. + # \param name The new name for the material. @pyqtSlot("QVariant", str) def setMaterialName(self, material_node: "MaterialNode", name: str) -> None: - if material_node.container is None: - return - root_material_id = material_node.container.getMetaDataEntry("base_file") - if root_material_id is None: - return - if CuraContainerRegistry.getInstance().isReadOnly(root_material_id): - Logger.log("w", "Cannot set name of read-only container %s.", root_material_id) - return - containers = CuraContainerRegistry.getInstance().findInstanceContainers(id = root_material_id) - containers[0].setName(name) + return cura.CuraApplication.CuraApplication.getMaterialManagementModel().setMaterialName(material_node, name) @pyqtSlot("QVariant") def removeMaterial(self, material_node: "MaterialNode") -> None: From b460ffeb9be8e905bfbf2f1aaef9446515fe453c Mon Sep 17 00:00:00 2001 From: Ghostkeeper Date: Tue, 17 Sep 2019 17:59:50 +0200 Subject: [PATCH 14/24] Use removeMaterial from MaterialManagementModel Contributes to issue CURA-6600. --- cura/Machines/MaterialManager.py | 16 +++++++++++----- 1 file changed, 11 insertions(+), 5 deletions(-) diff --git a/cura/Machines/MaterialManager.py b/cura/Machines/MaterialManager.py index a5cefcb8f4..dc9fb55902 100644 --- a/cura/Machines/MaterialManager.py +++ b/cura/Machines/MaterialManager.py @@ -275,13 +275,19 @@ class MaterialManager(QObject): def setMaterialName(self, material_node: "MaterialNode", name: str) -> None: return cura.CuraApplication.CuraApplication.getMaterialManagementModel().setMaterialName(material_node, name) + ## Deletes a material from Cura. + # + # This function does not do any safety checking any more. Please call this + # function only if: + # - The material is not read-only. + # - The material is not used in any stacks. + # If the material was not lazy-loaded yet, this will fully load the + # container. When removing this material node, all other materials with + # the same base fill will also be removed. + # \param material_node The material to remove. @pyqtSlot("QVariant") def removeMaterial(self, material_node: "MaterialNode") -> None: - if material_node.container is None: - return - root_material_id = material_node.container.getMetaDataEntry("base_file") - if root_material_id is not None: - self.removeMaterialByRootId(root_material_id) + return cura.CuraApplication.CuraApplication.getMaterialManagementModel().setMaterialName(material_node) def duplicateMaterialByRootId(self, root_material_id: str, new_base_id: Optional[str] = None, new_metadata: Optional[Dict[str, Any]] = None) -> Optional[str]: result = cura.CuraApplication.CuraApplication.getInstance().getMaterialManagementModel().duplicateMaterialByBaseFile(root_material_id, new_base_id, new_metadata) From 2571f54d3ca59acb6d5bd922c6fdd8df9fffd670 Mon Sep 17 00:00:00 2001 From: Ghostkeeper Date: Wed, 18 Sep 2019 14:01:23 +0200 Subject: [PATCH 15/24] Simplify looping over quality groups Contributes to issue CURA-6600. --- cura/Machines/Models/QualityProfilesDropDownMenuModel.py | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/cura/Machines/Models/QualityProfilesDropDownMenuModel.py b/cura/Machines/Models/QualityProfilesDropDownMenuModel.py index 2311e80689..8b3999275d 100644 --- a/cura/Machines/Models/QualityProfilesDropDownMenuModel.py +++ b/cura/Machines/Models/QualityProfilesDropDownMenuModel.py @@ -78,9 +78,7 @@ class QualityProfilesDropDownMenuModel(ListModel): quality_group_dict = ContainerTree.getInstance().getCurrentQualityGroups() item_list = [] - for key in quality_group_dict: - quality_group = quality_group_dict[key] - + for quality_group in quality_group_dict.values(): layer_height = self._fetchLayerHeight(quality_group) item = {"name": quality_group.name, From fade8d3644fbe26a90f1261deee6b58928ed6b41 Mon Sep 17 00:00:00 2001 From: Jaime van Kessel Date: Wed, 18 Sep 2019 14:10:52 +0200 Subject: [PATCH 16/24] No longer make border width hardcoded CURA-6598 --- resources/qml/PrintSetupSelector/Custom/MenuButton.qml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/resources/qml/PrintSetupSelector/Custom/MenuButton.qml b/resources/qml/PrintSetupSelector/Custom/MenuButton.qml index 29436da9cf..cebe130a20 100644 --- a/resources/qml/PrintSetupSelector/Custom/MenuButton.qml +++ b/resources/qml/PrintSetupSelector/Custom/MenuButton.qml @@ -22,7 +22,7 @@ Button background: Rectangle { id: backgroundRectangle - border.width: 1 + border.width: UM.Theme.getSize("default_lining").width border.color: button.checked ? UM.Theme.getColor("setting_control_border_highlight") : "transparent" color: button.hovered ? UM.Theme.getColor("action_button_hovered") : "transparent" radius: UM.Theme.getSize("action_button_radius").width From 84e5114566198862d185dcc87b4fedd6ea952a1f Mon Sep 17 00:00:00 2001 From: Jaime van Kessel Date: Wed, 18 Sep 2019 14:17:26 +0200 Subject: [PATCH 17/24] Fix minor review comments CURA-6598 --- .../Custom/QualitiesWithIntentMenu.qml | 3 ++- resources/qml/RadioCheckbar.qml | 14 +++++++------- 2 files changed, 9 insertions(+), 8 deletions(-) diff --git a/resources/qml/PrintSetupSelector/Custom/QualitiesWithIntentMenu.qml b/resources/qml/PrintSetupSelector/Custom/QualitiesWithIntentMenu.qml index 94f9acf3b3..cff4e3e7a6 100644 --- a/resources/qml/PrintSetupSelector/Custom/QualitiesWithIntentMenu.qml +++ b/resources/qml/PrintSetupSelector/Custom/QualitiesWithIntentMenu.qml @@ -182,11 +182,12 @@ Popup Rectangle { - height: 1 + height: UM.Theme.getSize("default_lining").height anchors.left: parent.left anchors.right: parent.right color: borderColor } + MenuButton { labelText: Cura.Actions.addProfile.text diff --git a/resources/qml/RadioCheckbar.qml b/resources/qml/RadioCheckbar.qml index 3c767a6201..59dba59910 100644 --- a/resources/qml/RadioCheckbar.qml +++ b/resources/qml/RadioCheckbar.qml @@ -14,7 +14,7 @@ Item property color activeColor: UM.Theme.getColor("primary") property color inactiveColor: UM.Theme.getColor("slider_groove") property color defaultItemColor: UM.Theme.getColor("small_button_active") - property int checkboxSize: UM.Theme.getSize("radio_button").height * 0.75 + property int checkboxSize: Math.round(UM.Theme.getSize("radio_button").height * 0.75) property int inactiveMarkerSize: 2 * barSize 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. @@ -36,8 +36,8 @@ Item { left: buttonBar.left right: buttonBar.right - leftMargin: (checkboxSize - inactiveMarkerSize) / 2 - rightMargin: (checkboxSize - inactiveMarkerSize) / 2 + leftMargin: Math.round((checkboxSize - inactiveMarkerSize) / 2) + rightMargin: Math.round((checkboxSize - inactiveMarkerSize) / 2) verticalCenter: parent.verticalCenter } } @@ -72,7 +72,7 @@ Item property Item previousItem: repeater.itemAt(index - 1) height: barSize - width: buttonBar.width / (repeater.count - 1) - activeComponent.width - 2 + width: Math.round(buttonBar.width / (repeater.count - 1) - activeComponent.width - 2) color: defaultItemColor anchors @@ -110,7 +110,7 @@ Item anchors.horizontalCenter: parent.horizontalCenter height: inactiveMarkerSize width: inactiveMarkerSize - radius: width / 2 + radius: Math.round(width / 2) color: inactiveColor } } @@ -132,7 +132,7 @@ Item { height: checkboxSize width: checkboxSize - radius: width / 2 + radius: Math.round(width / 2) border.color: defaultItemColor @@ -143,7 +143,7 @@ Item margins: 3 fill: parent } - radius: width / 2 + radius: Math.round(width / 2) color: activeColor visible: checkbox.checked } From a3e9316f4858581863cd7ead9b2d80c6f30e308f Mon Sep 17 00:00:00 2001 From: Ghostkeeper Date: Wed, 18 Sep 2019 14:26:41 +0200 Subject: [PATCH 18/24] Rename all_root_materials to all_base_files This naming is more consistent with the naming of the metadata entry and most of the other code. Contributes to issue CURA-6600. --- plugins/UM3NetworkPrinting/src/Network/SendMaterialJob.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/plugins/UM3NetworkPrinting/src/Network/SendMaterialJob.py b/plugins/UM3NetworkPrinting/src/Network/SendMaterialJob.py index 5637f388c1..e13ac96c40 100644 --- a/plugins/UM3NetworkPrinting/src/Network/SendMaterialJob.py +++ b/plugins/UM3NetworkPrinting/src/Network/SendMaterialJob.py @@ -69,9 +69,9 @@ class SendMaterialJob(Job): def _sendMaterials(self, materials_to_send: Set[str]) -> None: container_registry = CuraApplication.getInstance().getContainerRegistry() all_materials = container_registry.findInstanceContainersMetadata(type = "material") - all_root_materials = {material["base_file"] for material in all_materials if "base_file" in material} # Filters out uniques by making it a set. Don't include files without base file (i.e. empty material). + all_base_files = {material["base_file"] for material in all_materials if "base_file" in material} # Filters out uniques by making it a set. Don't include files without base file (i.e. empty material). - for root_material_id in all_root_materials: + for root_material_id in all_base_files: if root_material_id not in materials_to_send: # If the material does not have to be sent we skip it. continue From 05de920c21cc3cf262ecb376de86e6944c3852bb Mon Sep 17 00:00:00 2001 From: Ghostkeeper Date: Wed, 18 Sep 2019 14:28:22 +0200 Subject: [PATCH 19/24] Once more with feeling Sorry, I didn't see the other review comment until after I pushed the previous commit. Contributes to issue CURA-6600. --- plugins/UM3NetworkPrinting/src/Network/SendMaterialJob.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/plugins/UM3NetworkPrinting/src/Network/SendMaterialJob.py b/plugins/UM3NetworkPrinting/src/Network/SendMaterialJob.py index e13ac96c40..09949ed37e 100644 --- a/plugins/UM3NetworkPrinting/src/Network/SendMaterialJob.py +++ b/plugins/UM3NetworkPrinting/src/Network/SendMaterialJob.py @@ -129,10 +129,10 @@ class SendMaterialJob(Job): def _getLocalMaterials() -> Dict[str, LocalMaterial]: result = {} # type: Dict[str, LocalMaterial] all_materials = CuraApplication.getInstance().getContainerRegistry().findInstanceContainersMetadata(type = "material") - all_root_materials = [material for material in all_materials if material["id"] == material.get("base_file")] # Don't send materials without base_file: The empty material doesn't need to be sent. + all_base_files = [material for material in all_materials if material["id"] == material.get("base_file")] # Don't send materials without base_file: The empty material doesn't need to be sent. # Find the latest version of all material containers in the registry. - for material_metadata in all_root_materials: + for material_metadata in all_base_files: try: # material version must be an int material_metadata["version"] = int(material_metadata["version"]) From 7693de325ab51f82b43ab134b26a0a105939e084 Mon Sep 17 00:00:00 2001 From: Jaime van Kessel Date: Wed, 18 Sep 2019 14:39:06 +0200 Subject: [PATCH 20/24] Add loggin when user tries to change intent CURA-6598 --- cura/Settings/IntentManager.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/cura/Settings/IntentManager.py b/cura/Settings/IntentManager.py index 71f5e3705a..d4f12b9313 100644 --- a/cura/Settings/IntentManager.py +++ b/cura/Settings/IntentManager.py @@ -4,6 +4,7 @@ from PyQt5.QtCore import QObject, pyqtProperty, pyqtSignal, pyqtSlot from typing import Any, Dict, List, Optional, Set, Tuple, TYPE_CHECKING import cura.CuraApplication +from UM.Logger import Logger from cura.Machines.ContainerTree import ContainerTree from cura.Settings.cura_empty_instance_containers import empty_intent_container from UM.Settings.InstanceContainer import InstanceContainer @@ -11,6 +12,7 @@ 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. class IntentManager(QObject): @@ -131,6 +133,7 @@ class IntentManager(QObject): ## Apply intent on the stacks. @pyqtSlot(str, str) def selectIntent(self, intent_category: str, quality_type: str) -> None: + Logger.log("i", "Attempting to set intent_category to [%s] and quality type to [%s]", intent_category, quality_type) old_intent_category = self.currentIntentCategory application = cura.CuraApplication.CuraApplication.getInstance() global_stack = application.getGlobalContainerStack() From 78ab218cc21be78721de10ebdf39c4b24dc30eb8 Mon Sep 17 00:00:00 2001 From: Jaime van Kessel Date: Wed, 18 Sep 2019 14:52:51 +0200 Subject: [PATCH 21/24] No longer reset to default intent when configuration changed This caused the intent to be reset every time a change was made. CURA-6600 --- cura/Machines/Models/IntentCategoryModel.py | 4 ++-- cura/Settings/IntentManager.py | 18 +----------------- 2 files changed, 3 insertions(+), 19 deletions(-) diff --git a/cura/Machines/Models/IntentCategoryModel.py b/cura/Machines/Models/IntentCategoryModel.py index 5211889801..c436f94421 100644 --- a/cura/Machines/Models/IntentCategoryModel.py +++ b/cura/Machines/Models/IntentCategoryModel.py @@ -10,7 +10,7 @@ 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 PyQt5.QtCore import pyqtProperty, pyqtSignal - +import cura.CuraApplication if TYPE_CHECKING: from UM.Settings.ContainerRegistry import ContainerInterface @@ -48,7 +48,7 @@ class IntentCategoryModel(ListModel): ContainerRegistry.getInstance().containerAdded.connect(self._onContainerChange) ContainerRegistry.getInstance().containerRemoved.connect(self._onContainerChange) - IntentManager.getInstance().configurationChanged.connect(self.update) + cura.CuraApplication.CuraApplication.getInstance().getMachineManager().activeStackChanged.connect(self.update) self.update() diff --git a/cura/Settings/IntentManager.py b/cura/Settings/IntentManager.py index d4f12b9313..1a73fb818c 100644 --- a/cura/Settings/IntentManager.py +++ b/cura/Settings/IntentManager.py @@ -18,12 +18,6 @@ if TYPE_CHECKING: class IntentManager(QObject): __instance = None - def __init__(self) -> None: - super().__init__() - cura.CuraApplication.CuraApplication.getInstance().getMachineManager().activeStackChanged.connect(self.configurationChanged) - self.configurationChanged.connect(self.selectDefaultIntent) - pass - ## This class is a singleton. @classmethod def getInstance(cls): @@ -31,7 +25,6 @@ class IntentManager(QObject): cls.__instance = IntentManager() return cls.__instance - 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 @@ -150,13 +143,4 @@ 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: - 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() + self.intentCategoryChanged.emit() \ No newline at end of file From 49276db073c385c6f6be6f561556f28fe9c1082d Mon Sep 17 00:00:00 2001 From: Jaime van Kessel Date: Thu, 19 Sep 2019 09:39:52 +0200 Subject: [PATCH 22/24] Fix display of intent in profile selection CURA-6598 --- cura/Settings/MachineManager.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cura/Settings/MachineManager.py b/cura/Settings/MachineManager.py index ac44163898..b28d0fa27c 100755 --- a/cura/Settings/MachineManager.py +++ b/cura/Settings/MachineManager.py @@ -618,7 +618,7 @@ class MachineManager(QObject): if not self._active_container_stack: return "" - intent_category = self._active_container_stack.intent.getMetaDataEntry("intent_category") + intent_category = self._active_container_stack.intent.getMetaDataEntry("intent_category", "default") return intent_category ## Returns whether there is anything unsupported in the current set-up. From 884a3ea81960bc4502e781648e61d8fea46af77a Mon Sep 17 00:00:00 2001 From: Jaime van Kessel Date: Thu, 19 Sep 2019 09:54:47 +0200 Subject: [PATCH 23/24] Fix selection for intents if only one of the extruders has an intent CURA-6598 --- cura/Machines/Models/IntentModel.py | 16 +++++++++++++++- cura/Settings/MachineManager.py | 9 +++++++-- 2 files changed, 22 insertions(+), 3 deletions(-) diff --git a/cura/Machines/Models/IntentModel.py b/cura/Machines/Models/IntentModel.py index 8773a12fd3..79d26db8d3 100644 --- a/cura/Machines/Models/IntentModel.py +++ b/cura/Machines/Models/IntentModel.py @@ -66,12 +66,26 @@ class IntentModel(ListModel): container_tree = ContainerTree.getInstance() machine_node = container_tree.machines[global_stack.definition.getId()] - active_extruder = ExtruderManager.getInstance().getActiveExtruderStack() + + # We can't just look at the active extruder, since it is possible for only one extruder to have an intent + # and the other extruders have no intent (eg, default). It is not possible for one extruder to have intent A and + # the other to have B. + # So we will use the first extruder that we find that has an intent that is not default as the "active" extruder + + active_extruder = None + for extruder in global_stack.extruderList: + if extruder.intent.getMetaDataEntry("intent_category", "default") == "default": + if active_extruder is None: + active_extruder = extruder # If there is no extruder found and the intent is default, use that. + else: # We found an intent, use that extruder as "active" + active_extruder = extruder + if not active_extruder: return active_variant_name = active_extruder.variant.getMetaDataEntry("name") active_variant_node = machine_node.variants[active_variant_name] active_material_node = active_variant_node.materials[active_extruder.material.getMetaDataEntry("base_file")] + layer_heights_added = [] for quality_id, quality_node in active_material_node.qualities.items(): if quality_node.quality_type not in quality_groups: # Don't add the empty quality type (or anything else that would crash, defensively). diff --git a/cura/Settings/MachineManager.py b/cura/Settings/MachineManager.py index b28d0fa27c..c8fef837fc 100755 --- a/cura/Settings/MachineManager.py +++ b/cura/Settings/MachineManager.py @@ -615,10 +615,15 @@ class MachineManager(QObject): @pyqtProperty(str, notify=activeIntentChanged) def activeIntentCategory(self): + global_container_stack = cura.CuraApplication.CuraApplication.getInstance().getGlobalContainerStack() - if not self._active_container_stack: + if not global_container_stack: return "" - intent_category = self._active_container_stack.intent.getMetaDataEntry("intent_category", "default") + intent_category = "default" + for extruder in global_container_stack.extruderList: + category = extruder.intent.getMetaDataEntry("intent_category", "default") + if category != "default" and category != intent_category: + intent_category = category return intent_category ## Returns whether there is anything unsupported in the current set-up. From c76c183c6b994c63bd357ff5472778a820c283a9 Mon Sep 17 00:00:00 2001 From: Jaime van Kessel Date: Thu, 19 Sep 2019 13:45:13 +0200 Subject: [PATCH 24/24] Remove unused code --- cura/Settings/MachineManager.py | 8 -------- 1 file changed, 8 deletions(-) diff --git a/cura/Settings/MachineManager.py b/cura/Settings/MachineManager.py index c8fef837fc..4ff5ad95cd 100755 --- a/cura/Settings/MachineManager.py +++ b/cura/Settings/MachineManager.py @@ -1433,15 +1433,11 @@ class MachineManager(QObject): def setMaterialById(self, position: str, root_material_id: str) -> None: if self._global_container_stack is None: return - buildplate_name = None - if self._global_container_stack.variant.getId() != "empty_variant": - buildplate_name = self._global_container_stack.variant.getName() machine_definition_id = self._global_container_stack.definition.id position = str(position) extruder_stack = self._global_container_stack.extruders[position] nozzle_name = extruder_stack.variant.getName() - material_diameter = extruder_stack.getApproximateMaterialDiameter() material_node = ContainerTree.getInstance().machines[machine_definition_id].variants[nozzle_name].materials[root_material_id] self.setMaterial(position, material_node) @@ -1625,7 +1621,3 @@ class MachineManager(QObject): abbr_machine += stripped_word return abbr_machine - - # Gets all machines that belong to the given group_id. - def getMachinesInGroup(self, group_id: str) -> List["GlobalStack"]: - return self._container_registry.findContainerStacks(type = "machine", group_id = group_id)