diff --git a/cura/QualityManager.py b/cura/QualityManager.py index 97cf2a356a..a0341742f9 100644 --- a/cura/QualityManager.py +++ b/cura/QualityManager.py @@ -55,7 +55,9 @@ class QualityManager: # \return the matching quality changes containers \type{List[InstanceContainer]} def findQualityChangesByName(self, quality_changes_name: str, machine_definition: Optional["DefinitionContainerInterface"] = None): criteria = {"type": "quality_changes", "name": quality_changes_name} - result = self._getFilteredContainersForStack(machine_definition, [], **criteria) + + result = self.findAllQualityChangesForMachine(machine_definition) + result = [quality_change for quality_change in result if quality_change.getName() == quality_changes_name] return result diff --git a/cura/Settings/ContainerManager.py b/cura/Settings/ContainerManager.py index 25ed796526..1da0a7e3de 100644 --- a/cura/Settings/ContainerManager.py +++ b/cura/Settings/ContainerManager.py @@ -235,6 +235,40 @@ class ContainerManager(QObject): return True + ## Set a setting property value of the specified container. + # + # This will set the specified property of the specified setting of the container + # and all containers that share the same base_file (if any). The latter only + # happens for material containers. + # + # \param container_id \type{str} The ID of the container to change. + # \param setting_key \type{str} The key of the setting. + # \param property_name \type{str} The name of the property, eg "value". + # \param property_value \type{str} The new value of the property. + # + # \return True if successful, False if not. + @pyqtSlot(str, str, str, str, result = bool) + def setContainerProperty(self, container_id, setting_key, property_name, property_value): + containers = self._container_registry.findContainers(None, id = container_id) + if not containers: + Logger.log("w", "Could not set properties of container %s because it was not found.", container_id) + return False + + container = containers[0] + + if container.isReadOnly(): + Logger.log("w", "Cannot set properties of read-only container %s.", container_id) + return False + + container.setProperty(setting_key, property_name, property_value) + + basefile = container.getMetaDataEntry("base_file", container_id) + for sibbling_container in ContainerRegistry.getInstance().findInstanceContainers(base_file = basefile): + if sibbling_container != container: + sibbling_container.setProperty(setting_key, property_name, property_value) + + return True + ## Set the name of the specified container. @pyqtSlot(str, str, result = bool) def setContainerName(self, container_id, new_name): @@ -712,7 +746,7 @@ class ContainerManager(QObject): if not global_stack: return "" - approximate_diameter = round(global_stack.getProperty("material_diameter", "value")) + approximate_diameter = str(round(global_stack.getProperty("material_diameter", "value"))) containers = self._container_registry.findInstanceContainers(id = "generic_pla*", approximate_diameter = approximate_diameter) if not containers: Logger.log("d", "Unable to create a new material by cloning Generic PLA, because it cannot be found for the material diameter for this machine.") @@ -931,12 +965,6 @@ class ContainerManager(QObject): quality_changes.setDefinition(self._container_registry.findContainers(id = "fdmprinter")[0]) else: quality_changes.setDefinition(QualityManager.getInstance().getParentMachineDefinition(machine_definition)) - whole_machine_definition = QualityManager.getInstance().getWholeMachineDefinition(machine_definition) - - if whole_machine_definition.getMetaDataEntry("has_materials"): - material = quality_container.getMetaDataEntry("material") - if material is not None: - quality_changes.addMetaDataEntry("material", material) from cura.CuraApplication import CuraApplication quality_changes.addMetaDataEntry("setting_version", CuraApplication.SettingVersion) diff --git a/cura/Settings/ExtruderManager.py b/cura/Settings/ExtruderManager.py index ce6fd47de6..3baa2f5dce 100755 --- a/cura/Settings/ExtruderManager.py +++ b/cura/Settings/ExtruderManager.py @@ -310,9 +310,9 @@ class ExtruderManager(QObject): if preferred_material_id: global_stack = ContainerRegistry.getInstance().findContainerStacks(id = machine_id) if global_stack: - approximate_material_diameter = round(global_stack[0].getProperty("material_diameter", "value")) + approximate_material_diameter = str(round(global_stack[0].getProperty("material_diameter", "value"))) else: - approximate_material_diameter = round(machine_definition.getProperty("material_diameter", "value")) + approximate_material_diameter = str(round(machine_definition.getProperty("material_diameter", "value"))) search_criteria = { "type": "material", "id": preferred_material_id, "approximate_diameter": approximate_material_diameter} if machine_definition.getMetaDataEntry("has_machine_materials"): diff --git a/cura/Settings/MachineManager.py b/cura/Settings/MachineManager.py index 33372a3228..d0c04cd26a 100755 --- a/cura/Settings/MachineManager.py +++ b/cura/Settings/MachineManager.py @@ -1125,7 +1125,7 @@ class MachineManager(QObject): if not definition.getMetaDataEntry("has_materials"): return self._empty_material_container - approximate_material_diameter = round(stack.getProperty("material_diameter", "value")) + approximate_material_diameter = str(round(stack.getProperty("material_diameter", "value"))) search_criteria = { "type": "material", "approximate_diameter": approximate_material_diameter } if definition.getMetaDataEntry("has_machine_materials"): diff --git a/plugins/XmlMaterialProfile/XmlMaterialProfile.py b/plugins/XmlMaterialProfile/XmlMaterialProfile.py index 6e91e56930..04fc09019b 100644 --- a/plugins/XmlMaterialProfile/XmlMaterialProfile.py +++ b/plugins/XmlMaterialProfile/XmlMaterialProfile.py @@ -56,16 +56,14 @@ class XmlMaterialProfile(InstanceContainer): def setMetaDataEntry(self, key, value): if self.isReadOnly(): return - if self.getMetaDataEntry(key, None) == value: - # Prevent recursion caused by for loop. - return super().setMetaDataEntry(key, value) basefile = self.getMetaDataEntry("base_file", self._id) #if basefile is self.id, this is a basefile. - # Update all containers that share GUID and basefile + # Update all containers that share basefile for container in ContainerRegistry.getInstance().findInstanceContainers(base_file = basefile): - container.setMetaDataEntry(key, value) + if container.getMetaDataEntry(key, None) != value: # Prevent recursion + container.setMetaDataEntry(key, value) ## Overridden from InstanceContainer, similar to setMetaDataEntry. # without this function the setName would only set the name of the specific nozzle / material / machine combination container @@ -111,7 +109,7 @@ class XmlMaterialProfile(InstanceContainer): # container.setDirty(True) ## Overridden from InstanceContainer - # base file: global settings + supported machines + # base file: common settings + supported machines # machine / variant combination: only changes for itself. def serialize(self): registry = ContainerRegistry.getInstance() @@ -426,6 +424,8 @@ class XmlMaterialProfile(InstanceContainer): meta_data["base_file"] = self.id meta_data["status"] = "unknown" # TODO: Add material verfication + common_setting_values = {} + inherits = data.find("./um:inherits", self.__namespaces) if inherits is not None: inherited = self._resolveInheritance(inherits.text) @@ -455,6 +455,9 @@ class XmlMaterialProfile(InstanceContainer): continue meta_data[tag_name] = entry.text + if tag_name in self.__material_metadata_setting_map: + common_setting_values[self.__material_metadata_setting_map[tag_name]] = entry.text + if "description" not in meta_data: meta_data["description"] = "" @@ -467,45 +470,47 @@ class XmlMaterialProfile(InstanceContainer): tag_name = _tag_without_namespace(entry) property_values[tag_name] = entry.text - meta_data["approximate_diameter"] = round(float(property_values.get("diameter", 2.85))) # In mm + if tag_name in self.__material_properties_setting_map: + common_setting_values[self.__material_properties_setting_map[tag_name]] = entry.text + + meta_data["approximate_diameter"] = str(round(float(property_values.get("diameter", 2.85)))) # In mm meta_data["properties"] = property_values self.setDefinition(ContainerRegistry.getInstance().findDefinitionContainers(id = "fdmprinter")[0]) - global_compatibility = True - global_setting_values = {} + common_compatibility = True settings = data.iterfind("./um:settings/um:setting", self.__namespaces) for entry in settings: key = entry.get("key") - if key in self.__material_property_setting_map: - global_setting_values[self.__material_property_setting_map[key]] = entry.text + if key in self.__material_settings_setting_map: + common_setting_values[self.__material_settings_setting_map[key]] = entry.text elif key in self.__unmapped_settings: if key == "hardware compatible": - global_compatibility = parseBool(entry.text) + common_compatibility = parseBool(entry.text) else: Logger.log("d", "Unsupported material setting %s", key) - self._cached_values = global_setting_values + self._cached_values = common_setting_values # from InstanceContainer ancestor - meta_data["compatible"] = global_compatibility + meta_data["compatible"] = common_compatibility self.setMetaData(meta_data) self._dirty = False machines = data.iterfind("./um:settings/um:machine", self.__namespaces) for machine in machines: - machine_compatibility = global_compatibility + machine_compatibility = common_compatibility machine_setting_values = {} settings = machine.iterfind("./um:setting", self.__namespaces) for entry in settings: key = entry.get("key") - if key in self.__material_property_setting_map: - machine_setting_values[self.__material_property_setting_map[key]] = entry.text + if key in self.__material_settings_setting_map: + machine_setting_values[self.__material_settings_setting_map[key]] = entry.text elif key in self.__unmapped_settings: if key == "hardware compatible": machine_compatibility = parseBool(entry.text) else: Logger.log("d", "Unsupported material setting %s", key) - cached_machine_setting_properties = global_setting_values.copy() + cached_machine_setting_properties = common_setting_values.copy() cached_machine_setting_properties.update(machine_setting_values) identifiers = machine.iterfind("./um:machine_identifier", self.__namespaces) @@ -560,8 +565,8 @@ class XmlMaterialProfile(InstanceContainer): settings = hotend.iterfind("./um:setting", self.__namespaces) for entry in settings: key = entry.get("key") - if key in self.__material_property_setting_map: - hotend_setting_values[self.__material_property_setting_map[key]] = entry.text + if key in self.__material_settings_setting_map: + hotend_setting_values[self.__material_settings_setting_map[key]] = entry.text elif key in self.__unmapped_settings: if key == "hardware compatible": hotend_compatibility = parseBool(entry.text) @@ -591,7 +596,7 @@ class XmlMaterialProfile(InstanceContainer): def _addSettingElement(self, builder, instance): try: - key = UM.Dictionary.findKey(self.__material_property_setting_map, instance.definition.key) + key = UM.Dictionary.findKey(self.__material_settings_setting_map, instance.definition.key) except ValueError: return @@ -606,7 +611,7 @@ class XmlMaterialProfile(InstanceContainer): return material_name # Map XML file setting names to internal names - __material_property_setting_map = { + __material_settings_setting_map = { "print temperature": "default_material_print_temperature", "heated bed temperature": "material_bed_temperature", "standby temperature": "material_standby_temperature", @@ -618,6 +623,12 @@ class XmlMaterialProfile(InstanceContainer): __unmapped_settings = [ "hardware compatible" ] + __material_properties_setting_map = { + "diameter": "material_diameter" + } + __material_metadata_setting_map = { + "GUID": "material_guid" + } # Map XML file product names to internal ids # TODO: Move this to definition's metadata diff --git a/resources/qml/Menus/MaterialMenu.qml b/resources/qml/Menus/MaterialMenu.qml index cb1a4cf644..9127276f3d 100644 --- a/resources/qml/Menus/MaterialMenu.qml +++ b/resources/qml/Menus/MaterialMenu.qml @@ -150,7 +150,7 @@ Menu function materialFilter() { - var result = { "type": "material", "approximate_diameter": Math.round(materialDiameterProvider.properties.value) }; + var result = { "type": "material", "approximate_diameter": Math.round(materialDiameterProvider.properties.value).toString() }; if(Cura.MachineManager.filterMaterialsByMachine) { result.definition = Cura.MachineManager.activeQualityDefinitionId; diff --git a/resources/qml/Preferences/GeneralPage.qml b/resources/qml/Preferences/GeneralPage.qml index a01abb06ee..b40900fece 100755 --- a/resources/qml/Preferences/GeneralPage.qml +++ b/resources/qml/Preferences/GeneralPage.qml @@ -152,9 +152,10 @@ UM.PreferencesPage append({ text: "Suomi", code: "fi" }) append({ text: "Français", code: "fr" }) append({ text: "Italiano", code: "it" }) - append({ text: "日本語", code: "jp" }) + //append({ text: "日本語", code: "jp" }) + //append({ text: "한국어", code: "ko" }) append({ text: "Nederlands", code: "nl" }) - append({ text: "Português do Brasil", code: "ptbr" }) + //append({ text: "Português do Brasil", code: "ptbr" }) append({ text: "Русский", code: "ru" }) append({ text: "Türkçe", code: "tr" }) } diff --git a/resources/qml/Preferences/MaterialView.qml b/resources/qml/Preferences/MaterialView.qml index 9290126502..30edb063c1 100644 --- a/resources/qml/Preferences/MaterialView.qml +++ b/resources/qml/Preferences/MaterialView.qml @@ -164,7 +164,14 @@ TabView stepSize: 0.01 readOnly: !base.editingEnabled - onEditingFinished: base.setMetaDataEntry("properties/diameter", properties.diameter, value) + onEditingFinished: + { + // This does not use a SettingPropertyProvider, because we need to make the change to all containers + // which derive from the same base_file + base.setMetaDataEntry("approximate_diameter", properties.approximate_diameter, Math.round(value).toString()); + base.setMetaDataEntry("properties/diameter", properties.diameter, value); + Cura.ContainerManager.setContainerProperty(base.containerId, "material_diameter", "value", value); + } onValueChanged: updateCostPerMeter() } diff --git a/resources/qml/Preferences/MaterialsPage.qml b/resources/qml/Preferences/MaterialsPage.qml index c46b482d10..0921b8c7c2 100644 --- a/resources/qml/Preferences/MaterialsPage.qml +++ b/resources/qml/Preferences/MaterialsPage.qml @@ -24,7 +24,7 @@ UM.ManagementPage { filter: { - var result = { "type": "material", "approximate_diameter": Math.round(materialDiameterProvider.properties.value) } + var result = { "type": "material", "approximate_diameter": Math.round(materialDiameterProvider.properties.value).toString() } if(Cura.MachineManager.filterMaterialsByMachine) { result.definition = Cura.MachineManager.activeQualityDefinitionId; @@ -253,6 +253,7 @@ UM.ManagementPage property real density: 0.0; property real diameter: 0.0; + property string approximate_diameter: "0"; property real spool_cost: 0.0; property real spool_weight: 0.0; @@ -397,11 +398,13 @@ UM.ManagementPage { materialProperties.density = currentItem.metadata.properties.density ? currentItem.metadata.properties.density : 0.0; materialProperties.diameter = currentItem.metadata.properties.diameter ? currentItem.metadata.properties.diameter : 0.0; + materialProperties.approximate_diameter = currentItem.metadata.approximate_diameter ? currentItem.metadata.approximate_diameter : "0"; } else { materialProperties.density = 0.0; materialProperties.diameter = 0.0; + materialProperties.approximate_diameter = "0"; } }