diff --git a/cura/Machines/MaterialGroup.py b/cura/Machines/MaterialGroup.py index 009778943a..75ab51182c 100644 --- a/cura/Machines/MaterialGroup.py +++ b/cura/Machines/MaterialGroup.py @@ -15,10 +15,11 @@ # so "generic_abs_ultimaker3", "generic_abs_ultimaker3_AA_0.4", etc. # class MaterialGroup: - __slots__ = ("name", "root_material_node", "derived_material_node_list") + __slots__ = ("name", "is_read_only", "root_material_node", "derived_material_node_list") def __init__(self, name: str): self.name = name + self.is_read_only = False self.root_material_node = None self.derived_material_node_list = [] diff --git a/cura/Machines/MaterialManager.py b/cura/Machines/MaterialManager.py index 98e4f67f82..4bad33b890 100644 --- a/cura/Machines/MaterialManager.py +++ b/cura/Machines/MaterialManager.py @@ -87,6 +87,7 @@ class MaterialManager(QObject): root_material_id = material_metadata.get("base_file") if root_material_id not in self._material_group_map: self._material_group_map[root_material_id] = MaterialGroup(root_material_id) + self._material_group_map[root_material_id].is_read_only = self._container_registry.isReadOnly(root_material_id) group = self._material_group_map[root_material_id] # We only add root materials here @@ -325,6 +326,35 @@ class MaterialManager(QObject): return material_node + # + # Gets MaterialNode for the given extruder and machine with the given material type. + # Returns None if: + # 1. the given machine doesn't have materials; + # 2. cannot find any material InstanceContainers with the given settings. + # + def getMaterialNodeByType(self, global_stack: "GlobalStack", extruder_variant_name: str, material_guid: str) -> Optional["MaterialNode"]: + node = None + machine_definition = global_stack.definition + if parseBool(machine_definition.getMetaDataEntry("has_materials", False)): + material_diameter = machine_definition.getProperty("material_diameter", "value") + if isinstance(material_diameter, SettingFunction): + material_diameter = material_diameter(global_stack) + + # Look at the guid to material dictionary + root_material_id = None + for material_group in self._guid_material_groups_map[material_guid]: + if material_group.is_read_only: + root_material_id = material_group.root_material_node.metadata["id"] + break + + if not root_material_id: + Logger.log("i", "Cannot find materials with guid [%s] ", material_guid) + return None + + node = self.getMaterialNode(machine_definition.getId(), extruder_variant_name, + material_diameter, root_material_id) + return node + # # Used by QualityManager. Built-in quality profiles may be based on generic material IDs such as "generic_pla". # For materials such as ultimaker_pla_orange, no quality profiles may be found, so we should fall back to use diff --git a/cura/PrinterOutput/ExtruderConfigurationModel.py b/cura/PrinterOutput/ExtruderConfigurationModel.py index 7aa8785ae9..072adfc24e 100644 --- a/cura/PrinterOutput/ExtruderConfigurationModel.py +++ b/cura/PrinterOutput/ExtruderConfigurationModel.py @@ -24,7 +24,7 @@ class ExtruderConfigurationModel(QObject): def setMaterial(self, material): self._material = material - @pyqtProperty(str, fset = setMaterial, notify = extruderConfigurationChanged) + @pyqtProperty(QObject, fset = setMaterial, notify = extruderConfigurationChanged) def material(self): return self._material @@ -36,12 +36,14 @@ class ExtruderConfigurationModel(QObject): return self._hotend_id def __str__(self): - if self._material is None or self._hotend_id is None: + if self._material is None or self._hotend_id is None or self.material.type is None: return "No information" - return "Position: " + str(self._position) + " - Material: " + self._material + " - HotendID: " + self._hotend_id + return "Position: " + str(self._position) + " - Material: " + self._material.type + " - HotendID: " + self._hotend_id def __eq__(self, other): return hash(self) == hash(other) + # Calculating a hash function using the position of the extruder, the material GUID and the hotend id to check if is + # unique within a set def __hash__(self): - return hash(self._position) ^ hash(self._material) ^ hash(self._hotend_id) \ No newline at end of file + return hash(self._position) ^ (hash(self._material.guid) if self.material is not None else hash(0)) ^ hash(self._hotend_id) \ No newline at end of file diff --git a/cura/PrinterOutput/ExtruderOutputModel.py b/cura/PrinterOutput/ExtruderOutputModel.py index d74b3a90d5..a639d428f9 100644 --- a/cura/PrinterOutput/ExtruderOutputModel.py +++ b/cura/PrinterOutput/ExtruderOutputModel.py @@ -81,7 +81,6 @@ class ExtruderOutputModel(QObject): def _updateExtruderConfiguration(self): self._extruder_configuration.position = self._position - self._extruder_configuration.material = self._active_material.type if self.activeMaterial is not None else None + self._extruder_configuration.material = self._active_material self._extruder_configuration.hotendID = self._hotend_id - print("Recalculating extruder configuration:", self._extruder_configuration) self.extruderConfigurationChanged.emit() diff --git a/cura/PrinterOutput/PrinterOutputModel.py b/cura/PrinterOutput/PrinterOutputModel.py index 19365b9cc6..f59cc1bece 100644 --- a/cura/PrinterOutput/PrinterOutputModel.py +++ b/cura/PrinterOutput/PrinterOutputModel.py @@ -253,5 +253,4 @@ class PrinterOutputModel(QObject): self._printer_configuration.printerType = self._type self._printer_configuration.extruderConfigurations = [extruder.extruderConfiguration for extruder in self._extruders] self._printer_configuration.buildplateConfiguration = None # TODO Add the buildplate information - print("Recalculating printer configuration", self.name, ":", self._printer_configuration) self.configurationChanged.emit() diff --git a/cura/Settings/MachineManager.py b/cura/Settings/MachineManager.py index 0cde440fd8..6e0679e11c 100755 --- a/cura/Settings/MachineManager.py +++ b/cura/Settings/MachineManager.py @@ -20,7 +20,6 @@ from UM.Logger import Logger from UM.Message import Message from UM.Settings.ContainerRegistry import ContainerRegistry -from UM.Settings.InstanceContainer import InstanceContainer from UM.Settings.SettingFunction import SettingFunction from UM.Signal import postponeSignals, CompressTechnique @@ -28,6 +27,7 @@ from cura.Machines.QualityManager import getMachineDefinitionIDForQualitySearch from cura.PrinterOutputDevice import PrinterOutputDevice from cura.PrinterOutput.ConfigurationModel import ConfigurationModel from cura.PrinterOutput.ExtruderConfigurationModel import ExtruderConfigurationModel +from cura.PrinterOutput.MaterialOutputModel import MaterialOutputModel from cura.Settings.ExtruderManager import ExtruderManager from .CuraStackBuilder import CuraStackBuilder @@ -124,7 +124,8 @@ class MachineManager(QObject): if containers: containers[0].nameChanged.connect(self._onMaterialNameChanged) - self._material_manager = self._application._material_manager + self._material_manager = self._application.getMaterialManager() + self._variant_manager = self._application.getVariantManager() self._quality_manager = self._application.getQualityManager() # When the materials lookup table gets updated, it can mean that a material has its name changed, which should @@ -176,12 +177,21 @@ class MachineManager(QObject): if not self._global_container_stack: return + # Create the configuration model with the current data in Cura self._current_printer_configuration.printerType = self._global_container_stack.definition.getName() self._current_printer_configuration.extruderConfigurations = [] for extruder in self._global_container_stack.extruders.values(): extruder_configuration = ExtruderConfigurationModel() + # For compare just the GUID is needed at this moment + mat_type = extruder.material.getMetaDataEntry("material") if extruder.material != self._empty_material_container else None + mat_guid = extruder.material.getMetaDataEntry("GUID") if extruder.material != self._empty_material_container else None + mat_color = extruder.material.getMetaDataEntry("color_name") if extruder.material != self._empty_material_container else None + mat_brand = extruder.material.getMetaDataEntry("brand") if extruder.material != self._empty_material_container else None + mat_name = extruder.material.getMetaDataEntry("name") if extruder.material != self._empty_material_container else None + material_model = MaterialOutputModel(mat_guid, mat_type, mat_color, mat_brand, mat_name) + extruder_configuration.position = int(extruder.getMetaDataEntry("position")) - extruder_configuration.material = extruder.material.getName() if extruder.material != self._empty_material_container else None + extruder_configuration.material = material_model extruder_configuration.hotendID = extruder.variant.getName() if extruder.variant != self._empty_variant_container else None self._current_printer_configuration.extruderConfigurations.append(extruder_configuration) @@ -197,7 +207,8 @@ class MachineManager(QObject): @pyqtSlot(QObject) def applyRemoteConfiguration(self, configuration: ConfigurationModel): - print("Applying remote configuration", configuration) + for extruder_configuration in configuration.extruderConfigurations: + self.setConfiguration(extruder_configuration.position, extruder_configuration.hotendID, extruder_configuration.material.guid) @pyqtProperty("QVariantList", notify = outputDevicesChanged) def printerOutputDevices(self): @@ -355,6 +366,7 @@ class MachineManager(QObject): Logger.log("w", "Failed creating a new machine!") def _checkStacksHaveErrors(self) -> bool: + return False time_start = time.time() if self._global_container_stack is None: #No active machine. return False @@ -1018,6 +1030,16 @@ class MachineManager(QObject): self._updateMaterialWithVariant(None) # Update all materials self._updateQualityWithMaterial() + def setConfiguration(self, position, variant_name, material_guid): + position = str(position) + variant_container_node = self._variant_manager.getVariantNode(self._global_container_stack.definition.getId(), variant_name) + material_container_node = self._material_manager.getMaterialNodeByType(self._global_container_stack, variant_name, material_guid) + with postponeSignals(*self._getContainerChangedSignals(), compress = CompressTechnique.CompressPerParameterValue): + self._setVariantNode(position, variant_container_node) + self._setMaterial(position, material_container_node) + self._updateMaterialWithVariant(position) + self._updateQualityWithMaterial() + @pyqtSlot(str, "QVariant") def setMaterial(self, position, container_node): position = str(position) diff --git a/resources/qml/Menus/ConfigurationMenu/ConfigurationListView.qml b/resources/qml/Menus/ConfigurationMenu/ConfigurationListView.qml index 00de9d0003..f476383169 100644 --- a/resources/qml/Menus/ConfigurationMenu/ConfigurationListView.qml +++ b/resources/qml/Menus/ConfigurationMenu/ConfigurationListView.qml @@ -46,7 +46,6 @@ Column target: outputDevice onUniqueConfigurationsChanged: { // FIXME For now the model should be removed and then created again, otherwise changes in the printer don't automatically update the UI - print("Update unique configurations") configurationList.model = null configurationList.model = outputDevice.uniqueConfigurations } diff --git a/resources/qml/Menus/ConfigurationMenu/PrintCoreConfiguration.qml b/resources/qml/Menus/ConfigurationMenu/PrintCoreConfiguration.qml index 74ecc114c7..d34252adc4 100644 --- a/resources/qml/Menus/ConfigurationMenu/PrintCoreConfiguration.qml +++ b/resources/qml/Menus/ConfigurationMenu/PrintCoreConfiguration.qml @@ -69,7 +69,7 @@ Column Label { id: materialLabel - text: printCoreConfiguration.material + text: printCoreConfiguration.material.name elide: Text.ElideRight width: parent.width font: UM.Theme.getFont("default_bold")