diff --git a/cura/CuraApplication.py b/cura/CuraApplication.py index 6a89c86e85..ee0df6881a 100644 --- a/cura/CuraApplication.py +++ b/cura/CuraApplication.py @@ -85,10 +85,10 @@ class CuraApplication(QtApplication): self._open_file_queue = [] # Files to open when plug-ins are loaded. # Need to do this before ContainerRegistry tries to load the machines - SettingDefinition.addSupportedProperty("settable_per_mesh", DefinitionPropertyType.Any, default = True) - SettingDefinition.addSupportedProperty("settable_per_extruder", DefinitionPropertyType.Any, default = True) - SettingDefinition.addSupportedProperty("settable_per_meshgroup", DefinitionPropertyType.Any, default = True) - SettingDefinition.addSupportedProperty("settable_globally", DefinitionPropertyType.Any, default = True) + SettingDefinition.addSupportedProperty("settable_per_mesh", DefinitionPropertyType.Any, default = True, read_only = True) + SettingDefinition.addSupportedProperty("settable_per_extruder", DefinitionPropertyType.Any, default = True, read_only = True) + SettingDefinition.addSupportedProperty("settable_per_meshgroup", DefinitionPropertyType.Any, default = True, read_only = True) + SettingDefinition.addSupportedProperty("settable_globally", DefinitionPropertyType.Any, default = True, read_only = True) SettingDefinition.addSupportedProperty("global_inherits_stack", DefinitionPropertyType.Function, default = "-1") SettingDefinition.addSettingType("extruder", None, str, Validator) @@ -182,6 +182,10 @@ class CuraApplication(QtApplication): empty_quality_container._id = "empty_quality" empty_quality_container.addMetaDataEntry("type", "quality") ContainerRegistry.getInstance().addContainer(empty_quality_container) + empty_quality_changes_container = copy.deepcopy(empty_container) + empty_quality_changes_container._id = "empty_quality_changes" + empty_quality_changes_container.addMetaDataEntry("type", "quality_changes") + ContainerRegistry.getInstance().addContainer(empty_quality_changes_container) ContainerRegistry.getInstance().load() @@ -308,7 +312,7 @@ class CuraApplication(QtApplication): path = None if instance_type == "material": path = Resources.getStoragePath(self.ResourceTypes.MaterialInstanceContainer, file_name) - elif instance_type == "quality": + elif instance_type == "quality" or instance_type == "quality_changes": path = Resources.getStoragePath(self.ResourceTypes.QualityInstanceContainer, file_name) elif instance_type == "user": path = Resources.getStoragePath(self.ResourceTypes.UserInstanceContainer, file_name) @@ -476,6 +480,7 @@ class CuraApplication(QtApplication): qmlRegisterType(cura.Settings.ContainerSettingsModel, "Cura", 1, 0, "ContainerSettingsModel") qmlRegisterType(cura.Settings.MaterialSettingsVisibilityHandler, "Cura", 1, 0, "MaterialSettingsVisibilityHandler") + qmlRegisterType(cura.Settings.QualitySettingsModel, "Cura", 1, 0, "QualitySettingsModel") qmlRegisterSingletonType(cura.Settings.ContainerManager, "Cura", 1, 0, "ContainerManager", cura.Settings.ContainerManager.createContainerManager) diff --git a/cura/Settings/ContainerManager.py b/cura/Settings/ContainerManager.py index 82be7c480f..3dbd179700 100644 --- a/cura/Settings/ContainerManager.py +++ b/cura/Settings/ContainerManager.py @@ -14,6 +14,8 @@ import UM.Platform import UM.MimeTypeDatabase import UM.Logger +import cura.Settings + from UM.MimeTypeDatabase import MimeTypeNotFoundError from UM.i18n import i18nCatalog @@ -135,12 +137,11 @@ class ContainerManager(QObject): merge = containers[0] - if type(merge) != type(merge_into): + if not isinstance(merge, type(merge_into)): UM.Logger.log("w", "Cannot merge two containers of different types") return False - for key in merge.getAllKeys(): - merge_into.setProperty(key, "value", merge.getProperty(key, "value")) + self._performMerge(merge_into, merge) return True @@ -350,6 +351,188 @@ class ContainerManager(QObject): return { "status": "success", "message": "Successfully imported container {0}".format(container.getName()) } + ## Update the current active quality changes container with the settings from the user container. + # + # This will go through the active global stack and all active extruder stacks and merge the changes from the user + # container into the quality_changes container. After that, the user container is cleared. + # + # \return \type{bool} True if successful, False if not. + @pyqtSlot(result = bool) + def updateQualityChanges(self): + global_stack = UM.Application.getInstance().getGlobalContainerStack() + if not global_stack: + return False + + UM.Application.getInstance().getMachineManager().blurSettings.emit() + + for stack in cura.Settings.ExtruderManager.getInstance().getActiveGlobalAndExtruderStacks(): + # Find the quality_changes container for this stack and merge the contents of the top container into it. + quality_changes = stack.findContainer(type = "quality_changes") + if not quality_changes or quality_changes.isReadOnly(): + UM.Logger.log("e", "Could not update quality of a nonexistant or read only quality profile in stack %s", stack.getId()) + continue + + self._performMerge(quality_changes, stack.getTop()) + + UM.Application.getInstance().getMachineManager().activeQualityChanged.emit() + + return True + + ## Clear the top-most (user) containers of the active stacks. + @pyqtSlot() + def clearUserContainers(self): + UM.Application.getInstance().getMachineManager().blurSettings.emit() + + # Go through global and extruder stacks and clear their topmost container (the user settings). + for stack in cura.Settings.ExtruderManager.getInstance().getActiveGlobalAndExtruderStacks(): + stack.getTop().clear() + + ## Create quality changes containers from the user containers in the active stacks. + # + # This will go through the global and extruder stacks and create quality_changes containers from + # the user containers in each stack. These then replace the quality_changes containers in the + # stack and clear the user settings. + # + # \return \type{bool} True if the operation was successfully, False if not. + @pyqtSlot(result = bool) + def createQualityChanges(self): + global_stack = UM.Application.getInstance().getGlobalContainerStack() + if not global_stack: + return False + + quality_container = global_stack.findContainer(type = "quality") + if not quality_container: + UM.Logger.log("w", "No quality container found in stack %s, cannot create profile", global_stack.getId()) + return False + + UM.Application.getInstance().getMachineManager().blurSettings.emit() + + unique_name = UM.Settings.ContainerRegistry.getInstance().uniqueName(quality_container.getName()) + + # Go through the active stacks and create quality_changes containers from the user containers. + for stack in cura.Settings.ExtruderManager.getInstance().getActiveGlobalAndExtruderStacks(): + user_container = stack.getTop() + quality_container = stack.findContainer(type = "quality") + quality_changes_container = stack.findContainer(type = "quality_changes") + if not quality_container or not quality_changes_container: + UM.Logger.log("w", "No quality or quality changes container found in stack %s, ignoring it", stack.getId()) + continue + + new_changes = self._createQualityChanges(quality_container, unique_name, stack.getId()) + self._performMerge(new_changes, user_container) + + UM.Settings.ContainerRegistry.getInstance().addContainer(new_changes) + stack.replaceContainer(stack.getContainerIndex(quality_changes_container), new_changes) + + UM.Application.getInstance().getMachineManager().activeQualityChanged.emit() + return True + + ## Remove all quality changes containers matching a specified name. + # + # This will search for quality_changes containers matching the supplied name and remove them. + # Note that if the machine specifies that qualities should be filtered by machine and/or material + # only the containers related to the active machine/material are removed. + # + # \param quality_name The name of the quality changes to remove. + # + # \return \type{bool} True if successful, False if not. + @pyqtSlot(str, result = bool) + def removeQualityChanges(self, quality_name): + if not quality_name: + return False + + for container in self._getFilteredContainers(name = quality_name, type = "quality_changes"): + UM.Settings.ContainerRegistry.getInstance().removeContainer(container.getId()) + + return True + + ## Rename a set of quality changes containers. + # + # This will search for quality_changes containers matching the supplied name and rename them. + # Note that if the machine specifies that qualities should be filtered by machine and/or material + # only the containers related to the active machine/material are renamed. + # + # \param quality_name The name of the quality changes containers to rename. + # \param new_name The new name of the quality changes. + # + # \return True if successful, False if not. + @pyqtSlot(str, str, result = bool) + def renameQualityChanges(self, quality_name, new_name): + if not quality_name or not new_name: + return False + + if quality_name == new_name: + return True + + global_stack = UM.Application.getInstance().getGlobalContainerStack() + if not global_stack: + return False + + UM.Application.getInstance().getMachineManager().blurSettings.emit() + + new_name = UM.Settings.ContainerRegistry.getInstance().uniqueName(new_name) + + container_registry = UM.Settings.ContainerRegistry.getInstance() + for container in self._getFilteredContainers(name = quality_name, type = "quality_changes"): + stack_id = container.getMetaDataEntry("extruder", global_stack.getId()) + container_registry.renameContainer(container.getId(), new_name, self._createUniqueId(stack_id, new_name)) + + UM.Application.getInstance().getMachineManager().activeQualityChanged.emit() + return True + + ## Duplicate a specified set of quality or quality_changes containers. + # + # This will search for containers matching the specified name. If the container is a "quality" type container, a new + # quality_changes container will be created with the specified quality as base. If the container is a "quality_changes" + # container, it is simply duplicated and renamed. + # + # \param quality_name The name of the quality to duplicate. + # + # \return A string containing the name of the duplicated containers, or an empty string if it failed. + @pyqtSlot(str, result = str) + def duplicateQualityOrQualityChanges(self, quality_name): + global_stack = UM.Application.getInstance().getGlobalContainerStack() + if not global_stack or not quality_name: + return "" + + containers = UM.Settings.ContainerRegistry.getInstance().findInstanceContainers(name = quality_name) + if not containers: + return "" + + new_name = UM.Settings.ContainerRegistry.getInstance().uniqueName(quality_name) + + container_type = containers[0].getMetaDataEntry("type") + if container_type == "quality": + for container in self._getFilteredContainers(name = quality_name, type = "quality"): + for stack in cura.Settings.ExtruderManager.getInstance().getActiveGlobalAndExtruderStacks(): + new_changes = self._createQualityChanges(container, new_name, stack.getId()) + UM.Settings.ContainerRegistry.getInstance().addContainer(new_changes) + elif container_type == "quality_changes": + for container in self._getFilteredContainers(name = quality_name, type = "quality_changes"): + stack_id = container.getMetaDataEntry("extruder", global_stack.getId()) + new_container = container.duplicate(self._createUniqueId(stack_id, new_name), new_name) + UM.Settings.ContainerRegistry.getInstance().addContainer(new_container) + else: + return "" + + return new_name + + # Factory function, used by QML + @staticmethod + def createContainerManager(engine, js_engine): + return ContainerManager() + + def _performMerge(self, merge_into, merge): + assert isinstance(merge, type(merge_into)) + + if merge == merge_into: + return + + for key in merge.getAllKeys(): + merge_into.setProperty(key, "value", merge.getProperty(key, "value")) + + merge.clear() + def _updateContainerNameFilters(self): self._container_name_filters = {} for plugin_id, container_type in UM.Settings.ContainerRegistry.getContainerTypes(): @@ -394,7 +577,83 @@ class ContainerManager(QObject): name_filter = "{0} ({1})".format(mime_type.comment, suffix_list) self._container_name_filters[name_filter] = entry - # Factory function, used by QML - @staticmethod - def createContainerManager(engine, js_engine): - return ContainerManager() + ## Return a generator that iterates over a set of containers that are filtered by machine and material when needed. + # + # \param kwargs Initial search criteria that the containers need to match. + # + # \return A generator that iterates over the list of containers matching the search criteria. + def _getFilteredContainers(self, **kwargs): + global_stack = UM.Application.getInstance().getGlobalContainerStack() + if not global_stack: + return False + + criteria = kwargs + + filter_by_material = False + + if global_stack.getMetaDataEntry("has_machine_quality"): + criteria["definition"] = global_stack.getBottom().getId() + + filter_by_material = global_stack.getMetaDataEntry("has_materials") + + material_ids = [] + if filter_by_material: + for stack in cura.Settings.ExtruderManager.getInstance().getActiveGlobalAndExtruderStacks(): + material_ids.append(stack.findContainer(type = "material").getId()) + + containers = UM.Settings.ContainerRegistry.getInstance().findInstanceContainers(**criteria) + for container in containers: + # If the machine specifies we should filter by material, exclude containers that do not match any active material. + if filter_by_material and container.getMetaDataEntry("material") not in material_ids: + continue + + yield container + + ## Creates a unique ID for a container by prefixing the name with the stack ID. + # + # This method creates a unique ID for a container by prefixing it with a specified stack ID. + # This is done to ensure we have an easily identified ID for quality changes, which have the + # same name across several stacks. + # + # \param stack_id The ID of the stack to prepend. + # \param container_name The name of the container that we are creating a unique ID for. + # + # \return Container name prefixed with stack ID, in lower case with spaces replaced by underscores. + def _createUniqueId(self, stack_id, container_name): + result = stack_id + "_" + container_name + result = result.lower() + result.replace(" ", "_") + return result + + ## Create a quality changes container for a specified quality container. + # + # \param quality_container The quality container to create a changes container for. + # \param new_name The name of the new quality_changes container. + # \param stack_id The ID of the container stack the new container "belongs to". It is used primarily to ensure a unique ID. + # + # \return A new quality_changes container with the specified container as base. + def _createQualityChanges(self, quality_container, new_name, stack_id): + global_stack = UM.Application.getInstance().getGlobalContainerStack() + assert global_stack is not None + + # Create a new quality_changes container for the quality. + quality_changes = UM.Settings.InstanceContainer(self._createUniqueId(stack_id, new_name)) + quality_changes.setName(new_name) + quality_changes.addMetaDataEntry("type", "quality_changes") + quality_changes.addMetaDataEntry("quality", quality_container.getMetaDataEntry("quality_type")) + + # If we are creating a container for an extruder, ensure we add that to the container + if stack_id != global_stack.getId(): + quality_changes.addMetaDataEntry("extruder", stack_id) + + # If the machine specifies qualities should be filtered, ensure we match the current criteria. + if not global_stack.getMetaDataEntry("has_machine_quality"): + quality_changes.setDefinition(UM.Settings.ContainerRegistry.getInstance().findContainers(id = "fdmprinter")[0]) + else: + quality_changes.setDefinition(global_stack.getBottom()) + + if global_stack.getMetaDataEntry("has_materials"): + material = quality_container.getMetaDataEntry("material") + quality_changes.addMetaDataEntry("material", material) + + return quality_changes diff --git a/cura/Settings/ExtruderManager.py b/cura/Settings/ExtruderManager.py index 07216a158b..2b1bf6e234 100644 --- a/cura/Settings/ExtruderManager.py +++ b/cura/Settings/ExtruderManager.py @@ -235,6 +235,9 @@ class ExtruderManager(QObject): container_stack.addContainer(quality) + empty_quality_changes = container_registry.findInstanceContainers(id = "empty_quality_changes")[0] + container_stack.addContainer(empty_quality_changes) + user_profile = container_registry.findInstanceContainers(type = "user", extruder = extruder_stack_id) if user_profile: # There was already a user profile, loaded from settings. user_profile = user_profile[0] @@ -274,6 +277,20 @@ class ExtruderManager(QObject): for name in self._extruder_trains[machine_id]: yield self._extruder_trains[machine_id][name] + ## Returns a generator that will iterate over the global stack and per-extruder stacks. + # + # The first generated element is the global container stack. After that any extruder stacks are generated. + def getActiveGlobalAndExtruderStacks(self): + global_stack = UM.Application.getInstance().getGlobalContainerStack() + if not global_stack: + return + + yield global_stack + + global_id = global_stack.getId() + for name in self._extruder_trains[global_id]: + yield self._extruder_trains[global_id][name] + def __globalContainerStackChanged(self): self._addCurrentMachineExtruders() self.activeExtruderChanged.emit() diff --git a/cura/Settings/MachineManager.py b/cura/Settings/MachineManager.py index d4ccad5bae..b1d3f97f3e 100644 --- a/cura/Settings/MachineManager.py +++ b/cura/Settings/MachineManager.py @@ -26,16 +26,17 @@ class MachineManager(QObject): self._global_container_stack = None Application.getInstance().globalContainerStackChanged.connect(self._onGlobalContainerChanged) + ## When the global container is changed, active material probably needs to be updated. + self.globalContainerChanged.connect(self.activeMaterialChanged) + self.globalContainerChanged.connect(self.activeVariantChanged) + self.globalContainerChanged.connect(self.activeQualityChanged) + self._active_stack_valid = None self._onGlobalContainerChanged() ExtruderManager.getInstance().activeExtruderChanged.connect(self._onActiveExtruderStackChanged) self._onActiveExtruderStackChanged() - ## When the global container is changed, active material probably needs to be updated. - self.globalContainerChanged.connect(self.activeMaterialChanged) - self.globalContainerChanged.connect(self.activeVariantChanged) - self.globalContainerChanged.connect(self.activeQualityChanged) ExtruderManager.getInstance().activeExtruderChanged.connect(self.activeMaterialChanged) ExtruderManager.getInstance().activeExtruderChanged.connect(self.activeVariantChanged) ExtruderManager.getInstance().activeExtruderChanged.connect(self.activeQualityChanged) @@ -47,6 +48,7 @@ class MachineManager(QObject): self._empty_variant_container = UM.Settings.ContainerRegistry.getInstance().findInstanceContainers(id = "empty_variant")[0] self._empty_material_container = UM.Settings.ContainerRegistry.getInstance().findInstanceContainers(id = "empty_material")[0] self._empty_quality_container = UM.Settings.ContainerRegistry.getInstance().findInstanceContainers(id = "empty_quality")[0] + self._empty_quality_changes_container = UM.Settings.ContainerRegistry.getInstance().findInstanceContainers(id = "empty_quality_changes")[0] Preferences.getInstance().addPreference("cura/active_machine", "") @@ -184,107 +186,11 @@ class MachineManager(QObject): if old_index is not None: extruder_manager.setActiveExtruderIndex(old_index) - def _onGlobalPropertyChanged(self, key, property_name): - if property_name == "value": - ## We can get recursion issues. So we store a list of keys that we are still handling to prevent this. - if key in self._global_event_keys: - return - self._global_event_keys.add(key) - self.globalValueChanged.emit() - - if self._active_container_stack and self._active_container_stack != self._global_container_stack: - # Make the global current settings mirror the stack values appropriate for this setting - if self._active_container_stack.getProperty("extruder_nr", "value") == int(self._active_container_stack.getProperty(key, "global_inherits_stack")): - - new_value = self._active_container_stack.getProperty(key, "value") - self._global_container_stack.getTop().setProperty(key, "value", new_value) - - # Global-only setting values should be set on all extruders and the global stack - if not self._global_container_stack.getProperty(key, "settable_per_extruder"): - extruder_stacks = list(ExtruderManager.getInstance().getMachineExtruders(self._global_container_stack.getId())) - target_stack_position = int(self._active_container_stack.getProperty(key, "global_inherits_stack")) - if target_stack_position == -1: # Prevent -1 from selecting wrong stack. - target_stack = self._active_container_stack - else: - target_stack = extruder_stacks[target_stack_position] - new_value = target_stack.getProperty(key, "value") - target_stack_has_user_value = target_stack.getTop().getInstance(key) != None - for extruder_stack in extruder_stacks: - if extruder_stack != target_stack: - if target_stack_has_user_value: - extruder_stack.getTop().setProperty(key, "value", new_value) - else: - # Remove from the value from the other stacks as well, unless the - # top value from the other stacklevels is different than the new value - for container in extruder_stack.getContainers(): - if container.__class__ == UM.Settings.InstanceContainer and container.getInstance(key) != None: - if container.getProperty(key, "value") != new_value: - # It could be that the setting needs to be removed instead of updated. - temp = extruder_stack - containers = extruder_stack.getContainers() - # Ensure we have the entire 'chain' - while temp.getNextStack(): - temp = temp.getNextStack() - containers.extend(temp.getContainers()) - instance_needs_removal = False - - if len(containers) > 1: - for index in range(1, len(containers)): - deeper_container = containers[index] - if deeper_container.getProperty(key, "value") is None: - continue # Deeper container does not have the value, so continue. - if deeper_container.getProperty(key, "value") == new_value: - # Removal will result in correct value, so do that. - # We do this to prevent the reset from showing up unneeded. - instance_needs_removal = True - break - else: - # Container has the value, but it's not the same. Stop looking. - break - if instance_needs_removal: - extruder_stack.getTop().removeInstance(key) - else: - extruder_stack.getTop().setProperty(key, "value", new_value) - else: - # Check if we really need to remove something. - if extruder_stack.getProperty(key, "value") != new_value: - extruder_stack.getTop().removeInstance(key) - break - if self._global_container_stack.getProperty(key, "value") != new_value: - self._global_container_stack.getTop().setProperty(key, "value", new_value) - self._global_event_keys.remove(key) - - if property_name == "global_inherits_stack": - if self._active_container_stack and self._active_container_stack != self._global_container_stack: - # Update the global user value when the "global_inherits_stack" function points to a different stack - extruder_stacks = list(ExtruderManager.getInstance().getMachineExtruders(self._global_container_stack.getId())) - target_stack_position = int(self._active_container_stack.getProperty(key, "global_inherits_stack")) - if target_stack_position == -1: # Prevent -1 from selecting wrong stack. - target_stack = self._active_container_stack - else: - target_stack = extruder_stacks[target_stack_position] - - new_value = target_stack.getProperty(key, "value") - if self._global_container_stack.getProperty(key, "value") != new_value: - self._global_container_stack.getTop().setProperty(key, "value", new_value) - - if property_name == "validationState": - if self._active_stack_valid: - changed_validation_state = self._active_container_stack.getProperty(key, property_name) - if changed_validation_state in (UM.Settings.ValidatorState.Exception, UM.Settings.ValidatorState.MaximumError, UM.Settings.ValidatorState.MinimumError): - self._active_stack_valid = False - self.activeValidationChanged.emit() - else: - has_errors = self._checkStackForErrors(self._active_container_stack) - if not has_errors: - self._active_stack_valid = True - self.activeValidationChanged.emit() - def _onGlobalContainerChanged(self): if self._global_container_stack: self._global_container_stack.nameChanged.disconnect(self._onMachineNameChanged) self._global_container_stack.containersChanged.disconnect(self._onInstanceContainersChanged) - self._global_container_stack.propertyChanged.disconnect(self._onGlobalPropertyChanged) + self._global_container_stack.propertyChanged.disconnect(self._onPropertyChanged) material = self._global_container_stack.findContainer({"type": "material"}) material.nameChanged.disconnect(self._onMaterialNameChanged) @@ -301,7 +207,7 @@ class MachineManager(QObject): Preferences.getInstance().setValue("cura/active_machine", self._global_container_stack.getId()) self._global_container_stack.nameChanged.connect(self._onMachineNameChanged) self._global_container_stack.containersChanged.connect(self._onInstanceContainersChanged) - self._global_container_stack.propertyChanged.connect(self._onGlobalPropertyChanged) + self._global_container_stack.propertyChanged.connect(self._onPropertyChanged) material = self._global_container_stack.findContainer({"type": "material"}) material.nameChanged.connect(self._onMaterialNameChanged) @@ -312,11 +218,11 @@ class MachineManager(QObject): self.blurSettings.emit() # Ensure no-one has focus. if self._active_container_stack and self._active_container_stack != self._global_container_stack: self._active_container_stack.containersChanged.disconnect(self._onInstanceContainersChanged) - self._active_container_stack.propertyChanged.disconnect(self._onGlobalPropertyChanged) + self._active_container_stack.propertyChanged.disconnect(self._onPropertyChanged) self._active_container_stack = ExtruderManager.getInstance().getActiveExtruderStack() if self._active_container_stack: self._active_container_stack.containersChanged.connect(self._onInstanceContainersChanged) - self._active_container_stack.propertyChanged.connect(self._onGlobalPropertyChanged) + self._active_container_stack.propertyChanged.connect(self._onPropertyChanged) else: self._active_container_stack = self._global_container_stack self._active_stack_valid = not self._checkStackForErrors(self._active_container_stack) @@ -325,17 +231,6 @@ class MachineManager(QObject): def _onInstanceContainersChanged(self, container): container_type = container.getMetaDataEntry("type") - if self._active_container_stack and self._active_container_stack != self._global_container_stack: - if int(self._active_container_stack.getProperty("extruder_nr", "value")) == 0: - global_container = self._global_container_stack.findContainer({"type": container_type}) - if global_container and global_container != container: - container_index = self._global_container_stack.getContainerIndex(global_container) - self._global_container_stack.replaceContainer(container_index, container) - - for key in container.getAllKeys(): - # Make sure the values in this profile are distributed to other stacks if necessary - self._onGlobalPropertyChanged(key, "value") - if container_type == "material": self.activeMaterialChanged.emit() elif container_type == "variant": @@ -343,6 +238,23 @@ class MachineManager(QObject): elif container_type == "quality": self.activeQualityChanged.emit() + def _onPropertyChanged(self, key, property_name): + if property_name == "validationState": + if self._active_stack_valid: + if self._active_container_stack.getProperty(key, "settable_per_extruder"): + changed_validation_state = self._active_container_stack.getProperty(key, property_name) + else: + changed_validation_state = self._global_container_stack.getProperty(key, property_name) + if changed_validation_state in (UM.Settings.ValidatorState.Exception, UM.Settings.ValidatorState.MaximumError, UM.Settings.ValidatorState.MinimumError): + self._active_stack_valid = False + self.activeValidationChanged.emit() + else: + if not self._checkStackForErrors(self._active_container_stack) and not self._checkStackForErrors(self._global_container_stack): + self._active_stack_valid = True + self.activeValidationChanged.emit() + + self.activeStackChanged.emit() + @pyqtSlot(str) def setActiveMachine(self, stack_id): containers = UM.Settings.ContainerRegistry.getInstance().findContainerStacks(id = stack_id) @@ -370,7 +282,6 @@ class MachineManager(QObject): current_settings_instance_container.setDefinition(definitions[0]) container_registry.addContainer(current_settings_instance_container) - # If a definition is found, its a list. Should only have one item. new_global_stack.addContainer(definition) if variant_instance_container: new_global_stack.addContainer(variant_instance_container) @@ -378,6 +289,8 @@ class MachineManager(QObject): new_global_stack.addContainer(material_instance_container) if quality_instance_container: new_global_stack.addContainer(quality_instance_container) + + new_global_stack.addContainer(self._empty_quality_changes_container) new_global_stack.addContainer(current_settings_instance_container) ExtruderManager.getInstance().addMachineExtruders(definition, new_global_stack.getId()) @@ -418,11 +331,17 @@ class MachineManager(QObject): ## Check if the global_container has instances in the user container @pyqtProperty(bool, notify = activeStackChanged) def hasUserSettings(self): - if not self._active_container_stack: + if not self._global_container_stack: return False - user_settings = self._active_container_stack.getTop().findInstances(**{}) - return len(user_settings) != 0 + if self._global_container_stack.getTop().findInstances(): + return True + + for stack in ExtruderManager.getInstance().getMachineExtruders(self._global_container_stack.getId()): + if stack.getTop().findInstances(): + return True + + return False ## Check if the global profile does not contain error states # Note that the _active_stack_valid is cached due to performance issues @@ -477,6 +396,22 @@ class MachineManager(QObject): return "" + @pyqtProperty("QVariantMap", notify = activeMaterialChanged) + def allActiveMaterialIds(self): + if not self._global_container_stack: + return {} + + result = {} + + for stack in ExtruderManager.getInstance().getActiveGlobalAndExtruderStacks(): + material_container = stack.findContainer(type = "material") + if not material_container: + continue + + result[stack.getId()] = material_container.getId() + + return result + @pyqtProperty(str, notify=activeQualityChanged) def activeQualityMaterialId(self): if self._active_container_stack: @@ -489,6 +424,9 @@ class MachineManager(QObject): @pyqtProperty(str, notify=activeQualityChanged) def activeQualityName(self): if self._active_container_stack: + quality = self._active_container_stack.findContainer({"type": "quality_changes"}) + if quality and quality != self._empty_quality_changes_container: + return quality.getName() quality = self._active_container_stack.findContainer({"type": "quality"}) if quality: return quality.getName() @@ -496,12 +434,31 @@ class MachineManager(QObject): @pyqtProperty(str, notify=activeQualityChanged) def activeQualityId(self): - if self._active_container_stack: - quality = self._active_container_stack.findContainer({"type": "quality"}) + if self._global_container_stack: + quality = self._global_container_stack.findContainer({"type": "quality_changes"}) + if quality and quality != self._empty_quality_changes_container: + return quality.getId() + quality = self._global_container_stack.findContainer({"type": "quality"}) if quality: return quality.getId() return "" + @pyqtProperty(str, notify = activeQualityChanged) + def activeQualityType(self): + if self._global_container_stack: + quality = self._global_container_stack.findContainer(type = "quality") + if quality: + return quality.getMetaDataEntry("quality_type") + return "" + + @pyqtProperty(str, notify = activeQualityChanged) + def activeQualityChangesId(self): + if self._global_container_stack: + changes = self._global_container_stack.findContainer(type = "quality_changes") + if changes: + return changes.getId() + return "" + ## Check if a container is read_only @pyqtSlot(str, result = bool) def isReadOnly(self, container_id): @@ -523,104 +480,6 @@ class MachineManager(QObject): if extruder_stack != self._active_container_stack and extruder_stack.getProperty(key, "value") != new_value: extruder_stack.getTop().setProperty(key, "value", new_value) - @pyqtSlot(result = str) - def newQualityContainerFromQualityAndUser(self): - new_container_id = self.duplicateContainer(self.activeQualityId) - if new_container_id == "": - return - self.blurSettings.emit() - self.updateQualityContainerFromUserContainer(new_container_id) - self.setActiveQuality(new_container_id) - return new_container_id - - @pyqtSlot(str, result=str) - def duplicateContainer(self, container_id): - if not self._active_container_stack: - return "" - containers = UM.Settings.ContainerRegistry.getInstance().findInstanceContainers(id = container_id) - if containers: - new_name = self._createUniqueName("quality", "", containers[0].getName(), catalog.i18nc("@label", "Custom profile")) - - new_container = containers[0].duplicate(new_name, new_name) - - UM.Settings.ContainerRegistry.getInstance().addContainer(new_container) - - return new_name - - return "" - - @pyqtSlot(str, str) - def renameQualityContainer(self, container_id, new_name): - containers = UM.Settings.ContainerRegistry.getInstance().findInstanceContainers(id = container_id, type = "quality") - if containers: - new_name = self._createUniqueName("quality", containers[0].getName(), new_name, - catalog.i18nc("@label", "Custom profile")) - - if containers[0].getName() == new_name: - # Nothing to do. - return - - # As we also want the id of the container to be changed (so that profile name is the name of the file - # on disk. We need to create a new instance and remove it (so the old file of the container is removed) - # If we don't do that, we might get duplicates & other weird issues. - new_container = UM.Settings.InstanceContainer("") - new_container.deserialize(containers[0].serialize()) - - # Actually set the name - new_container.setName(new_name) - new_container._id = new_name # Todo: Fix proper id change function for this. - - # Add the "new" container. - UM.Settings.ContainerRegistry.getInstance().addContainer(new_container) - - # Ensure that the renamed profile is saved -before- we remove the old profile. - Application.getInstance().saveSettings() - - # Actually set & remove new / old quality. - self.setActiveQuality(new_name) - self.removeQualityContainer(containers[0].getId()) - - @pyqtSlot(str) - def removeQualityContainer(self, container_id): - containers = UM.Settings.ContainerRegistry.getInstance().findInstanceContainers(id = container_id) - if not containers or not self._active_container_stack: - return - - # If the container that is being removed is the currently active container, set another machine as the active container - activate_new_container = container_id == self.activeQualityId - - UM.Settings.ContainerRegistry.getInstance().removeContainer(container_id) - - if activate_new_container: - definition_id = "fdmprinter" if not self.filterQualityByMachine else self.activeDefinitionId - containers = UM.Settings.ContainerRegistry.getInstance().findInstanceContainers(type = "quality", definition = definition_id) - if containers: - self.setActiveQuality(containers[0].getId()) - self.activeQualityChanged.emit() - - @pyqtSlot(str) - @pyqtSlot() - def updateQualityContainerFromUserContainer(self, quality_id = None): - if not self._active_container_stack: - return - - if quality_id: - quality = UM.Settings.ContainerRegistry.getInstance().findInstanceContainers(id = quality_id, type = "quality") - if quality: - quality = quality[0] - else: - quality = self._active_container_stack.findContainer({"type": "quality"}) - - if not quality: - return - - user_settings = self._active_container_stack.getTop() - - for key in user_settings.getAllKeys(): - quality.setProperty(key, "value", user_settings.getProperty(key, "value")) - self.clearUserSettings() # As all users settings are noq a quality, remove them. - - @pyqtSlot(str) def setActiveMaterial(self, material_id): containers = UM.Settings.ContainerRegistry.getInstance().findInstanceContainers(id = material_id) @@ -667,32 +526,81 @@ class MachineManager(QObject): @pyqtSlot(str) def setActiveQuality(self, quality_id): containers = UM.Settings.ContainerRegistry.getInstance().findInstanceContainers(id = quality_id) - if not containers or not self._active_container_stack: + if not containers or not self._global_container_stack: return - old_quality = self._active_container_stack.findContainer({"type": "quality"}) - if old_quality and old_quality != containers[0]: - old_quality.nameChanged.disconnect(self._onQualityNameChanged) + quality_container = None + quality_changes_container = self._empty_quality_changes_container - quality_index = self._active_container_stack.getContainerIndex(old_quality) + container_type = containers[0].getMetaDataEntry("type") - self._active_container_stack.replaceContainer(quality_index, containers[0]) - - containers[0].nameChanged.connect(self._onQualityNameChanged) - - if self.hasUserSettings and Preferences.getInstance().getValue("cura/active_mode") == 1: - # Ask the user if the user profile should be cleared or not (discarding the current settings) - # In Simple Mode we assume the user always wants to keep the (limited) current settings - details = catalog.i18nc("@label", "You made changes to the following setting(s):") - user_settings = self._active_container_stack.getTop().findInstances(**{}) - for setting in user_settings: - details = details + "\n " + setting.definition.label - - Application.getInstance().messageBox(catalog.i18nc("@window:title", "Switched profiles"), catalog.i18nc("@label", "Do you want to transfer your changed settings to this profile?"), - catalog.i18nc("@label", "If you transfer your settings they will override settings in the profile."), details, - buttons = QMessageBox.Yes + QMessageBox.No, icon = QMessageBox.Question, callback = self._keepUserSettingsDialogCallback) + if container_type == "quality": + quality_container = containers[0] + elif container_type == "quality_changes": + quality_changes_container = containers[0] + containers = UM.Settings.ContainerRegistry.getInstance().findInstanceContainers( + quality_type = quality_changes_container.getMetaDataEntry("quality")) + if not containers: + Logger.log("e", "Could not find quality %s for changes %s, not changing quality", quality_changes_container.getMetaDataEntry("quality"), quality_changes_container.getId()) + return + quality_container = containers[0] else: - Logger.log("w", "While trying to set the active quality, no quality was found to replace.") + Logger.log("e", "Tried to set quality to a container that is not of the right type") + return + + quality_type = quality_container.getMetaDataEntry("quality_type") + if not quality_type: + quality_type = quality_changes_container.getName() + + for stack in ExtruderManager.getInstance().getActiveGlobalAndExtruderStacks(): + extruder_id = stack.getId() if stack != self._global_container_stack else None + + criteria = { "quality_type": quality_type, "extruder": extruder_id } + + if self._global_container_stack.getMetaDataEntry("has_machine_quality"): + material = stack.findContainer(type = "material") + criteria["material"] = material.getId() + + stack_quality = UM.Settings.ContainerRegistry.getInstance().findInstanceContainers(**criteria) + if not stack_quality: + criteria.pop("extruder") + stack_quality = UM.Settings.ContainerRegistry.getInstance().findInstanceContainers(**criteria) + if not stack_quality: + stack_quality = quality_container + else: + stack_quality = stack_quality[0] + else: + stack_quality = stack_quality[0] + + if quality_changes_container != self._empty_quality_changes_container: + stack_quality_changes = UM.Settings.ContainerRegistry.getInstance().findInstanceContainers(name = quality_changes_container.getName(), extruder = extruder_id)[0] + else: + stack_quality_changes = self._empty_quality_changes_container + + old_quality = stack.findContainer(type = "quality") + old_quality.nameChanged.disconnect(self._onQualityNameChanged) + old_changes = stack.findContainer(type = "quality_changes") + old_changes.nameChanged.disconnect(self._onQualityNameChanged) + + stack.replaceContainer(stack.getContainerIndex(old_quality), stack_quality) + stack.replaceContainer(stack.getContainerIndex(old_changes), stack_quality_changes) + + stack_quality.nameChanged.connect(self._onQualityNameChanged) + stack_quality_changes.nameChanged.connect(self._onQualityNameChanged) + + if self.hasUserSettings and Preferences.getInstance().getValue("cura/active_mode") == 1: + # Ask the user if the user profile should be cleared or not (discarding the current settings) + # In Simple Mode we assume the user always wants to keep the (limited) current settings + details = catalog.i18nc("@label", "You made changes to the following setting(s):") + user_settings = self._active_container_stack.getTop().findInstances(**{}) + for setting in user_settings: + details = details + "\n " + setting.definition.label + + Application.getInstance().messageBox(catalog.i18nc("@window:title", "Switched profiles"), catalog.i18nc("@label", "Do you want to transfer your changed settings to this profile?"), + catalog.i18nc("@label", "If you transfer your settings they will override settings in the profile."), details, + buttons = QMessageBox.Yes + QMessageBox.No, icon = QMessageBox.Question, callback = self._keepUserSettingsDialogCallback) + + self.activeQualityChanged.emit() def _keepUserSettingsDialogCallback(self, button): if button == QMessageBox.Yes: @@ -700,7 +608,11 @@ class MachineManager(QObject): pass elif button == QMessageBox.No: # No, discard the settings in the user profile - self.clearUserSettings() + global_stack = Application.getInstance().getGlobalContainerStack() + for extruder in ExtruderManager.getInstance().getMachineExtruders(global_stack.getId()): + extruder.getTop().clear() + + global_stack.getTop().clear() @pyqtProperty(str, notify = activeVariantChanged) def activeVariantName(self): diff --git a/cura/Settings/QualitySettingsModel.py b/cura/Settings/QualitySettingsModel.py new file mode 100644 index 0000000000..da8eaeebaf --- /dev/null +++ b/cura/Settings/QualitySettingsModel.py @@ -0,0 +1,156 @@ +# Copyright (c) 2016 Ultimaker B.V. +# Cura is released under the terms of the AGPLv3 or higher. + +import collections + +from PyQt5.QtCore import pyqtProperty, pyqtSignal, Qt + +import UM.Application +import UM.Logger +import UM.Qt +import UM.Settings + + +class QualitySettingsModel(UM.Qt.ListModel.ListModel): + KeyRole = Qt.UserRole + 1 + LabelRole = Qt.UserRole + 2 + UnitRole = Qt.UserRole + 3 + ProfileValueRole = Qt.UserRole + 4 + UserValueRole = Qt.UserRole + 5 + CategoryRole = Qt.UserRole + 6 + + def __init__(self, parent = None): + super().__init__(parent = parent) + + self._extruder_id = None + self._quality = None + self._material = None + + self.addRoleName(self.KeyRole, "key") + self.addRoleName(self.LabelRole, "label") + self.addRoleName(self.UnitRole, "unit") + self.addRoleName(self.ProfileValueRole, "profile_value") + self.addRoleName(self.UserValueRole, "user_value") + self.addRoleName(self.CategoryRole, "category") + + def setExtruderId(self, extruder_id): + if extruder_id != self._extruder_id: + self._extruder_id = extruder_id + self._update() + self.extruderIdChanged.emit() + + extruderIdChanged = pyqtSignal() + @pyqtProperty(str, fset = setExtruderId, notify = extruderIdChanged) + def extruderId(self): + return self._extruder_id + + def setQuality(self, quality): + if quality != self._quality: + self._quality = quality + self._update() + self.qualityChanged.emit() + + qualityChanged = pyqtSignal() + @pyqtProperty(str, fset = setQuality, notify = qualityChanged) + def quality(self): + return self._quality + + def setMaterial(self, material): + if material != self._material: + self._material = material + self._update() + self.materialChanged.emit() + + materialChanged = pyqtSignal() + @pyqtProperty(str, fset = setMaterial, notify = materialChanged) + def material(self): + return self._material + + def _update(self): + if not self._quality: + return + + self.clear() + + settings = collections.OrderedDict() + definition_container = UM.Application.getInstance().getGlobalContainerStack().getBottom() + + containers = UM.Settings.ContainerRegistry.getInstance().findInstanceContainers(id = self._quality) + if not containers: + UM.Logger.log("w", "Could not find a quality container with id %s", self._quality) + return + + quality_container = None + quality_changes_container = None + + if containers[0].getMetaDataEntry("type") == "quality": + quality_container = containers[0] + else: + quality_changes_container = containers[0] + + criteria = { "type": "quality", "quality_type": quality_changes_container.getMetaDataEntry("quality"), "definition": quality_changes_container.getDefinition().getId() } + + if self._material: + criteria["material"] = self._material + + quality_container = UM.Settings.ContainerRegistry.getInstance().findInstanceContainers(**criteria) + if not quality_container: + UM.Logger.log("w", "Could not find a quality container matching quality changes %s", quality_changes_container.getId()) + return + quality_container = quality_container[0] + + quality_type = quality_container.getMetaDataEntry("quality_type") + + criteria = { "type": "quality", "quality_type": quality_type } + + if self._material: + criteria["material"] = self._material + + criteria["extruder"] = self._extruder_id + + containers = UM.Settings.ContainerRegistry.getInstance().findInstanceContainers(**criteria) + if not containers: + # Try again, this time without extruder + criteria.pop("extruder") + containers = UM.Settings.ContainerRegistry.getInstance().findInstanceContainers(**criteria) + + if not containers: + UM.Logger.log("Could not find any quality containers matching the search criteria %s", criteria) + return + + if quality_changes_container: + changes = UM.Settings.ContainerRegistry.getInstance().findInstanceContainers(type = "quality_changes", quality = quality_type, extruder = self._extruder_id) + if changes: + containers.extend(changes) + + current_category = "" + for definition in definition_container.findDefinitions(): + if definition.type == "category": + current_category = definition.label + continue + + profile_value = None + for container in containers: + new_value = container.getProperty(definition.key, "value") + if new_value: + profile_value = new_value + + user_value = None + if not self._extruder_id: + user_value = UM.Application.getInstance().getGlobalContainerStack().getTop().getProperty(definition.key, "value") + else: + extruder_stack = UM.Settings.ContainerRegistry.getInstance().findContainerStacks(id = self._extruder_id) + if extruder_stack: + user_value = extruder_stack[0].getTop().getProperty(definition.key, "value") + + if not profile_value and not user_value: + continue + + self.appendItem({ + "key": definition.key, + "label": definition.label, + "unit": definition.unit, + "profile_value": "" if profile_value is None else str(profile_value), # it is for display only + "user_value": "" if user_value is None else str(user_value), + "category": current_category + }) diff --git a/cura/Settings/__init__.py b/cura/Settings/__init__.py index da8f36c040..5daa00c84f 100644 --- a/cura/Settings/__init__.py +++ b/cura/Settings/__init__.py @@ -10,3 +10,4 @@ from .ExtrudersModel import ExtrudersModel from .MachineManager import MachineManager from .MaterialSettingsVisibilityHandler import MaterialSettingsVisibilityHandler from .SettingOverrideDecorator import SettingOverrideDecorator +from .QualitySettingsModel import QualitySettingsModel diff --git a/resources/qml/Actions.qml b/resources/qml/Actions.qml index 536ec289fe..9b9e85650f 100644 --- a/resources/qml/Actions.qml +++ b/resources/qml/Actions.qml @@ -122,7 +122,7 @@ Item id: updateProfileAction; enabled: Cura.MachineManager.isActiveStackValid && Cura.MachineManager.hasUserSettings && !Cura.MachineManager.isReadOnly(Cura.MachineManager.activeQualityId) text: catalog.i18nc("@action:inmenu menubar:profile","&Update profile with current settings"); - onTriggered: Cura.MachineManager.updateQualityContainerFromUserContainer() + onTriggered: Cura.ContainerManager.updateQualityChanges(); } Action @@ -130,7 +130,7 @@ Item id: resetProfileAction; enabled: Cura.MachineManager.hasUserSettings text: catalog.i18nc("@action:inmenu menubar:profile","&Discard current settings"); - onTriggered: Cura.MachineManager.clearUserSettings(); + onTriggered: Cura.ContainerManager.clearUserContainers(); } Action diff --git a/resources/qml/Cura.qml b/resources/qml/Cura.qml index 5f45a062b8..fc808c1434 100644 --- a/resources/qml/Cura.qml +++ b/resources/qml/Cura.qml @@ -150,7 +150,7 @@ UM.MainWindow MenuSeparator { } - MenuItem { text: "Set as Active Extruder" } + MenuItem { text: catalog.i18nc("@action:inmenu", "Set as Active Extruder"); onTriggered: Cura.ExtruderManager.setActiveExtruderIndex(model.index) } } onObjectAdded: settingsMenu.insertItem(index, object) onObjectRemoved: settingsMenu.removeItem(object) @@ -459,7 +459,7 @@ UM.MainWindow target: Cura.Actions.addProfile onTriggered: { - Cura.MachineManager.newQualityContainerFromQualityAndUser(); + Cura.ContainerManager.createQualityChanges(); preferences.setPage(4); preferences.show(); diff --git a/resources/qml/Menus/ProfileMenu.qml b/resources/qml/Menus/ProfileMenu.qml index fcc97e5ea2..1c9161cd49 100644 --- a/resources/qml/Menus/ProfileMenu.qml +++ b/resources/qml/Menus/ProfileMenu.qml @@ -7,7 +7,7 @@ import QtQuick.Controls 1.1 import UM 1.2 as UM import Cura 1.0 as Cura - Menu +Menu { id: menu @@ -15,14 +15,14 @@ import Cura 1.0 as Cura { model: UM.InstanceContainersModel { - filter: menu.getFilter({ "read_only": true }); + filter: menu.getFilter({ "type": "quality" }); } MenuItem { text: model.name checkable: true - checked: Cura.MachineManager.activeQualityId == model.id + checked: Cura.MachineManager.activeQualityChangesId == "empty_quality_changes" && Cura.MachineManager.activeQualityType == model.metadata.quality_type exclusiveGroup: group onTriggered: Cura.MachineManager.setActiveQuality(model.id) } @@ -38,7 +38,7 @@ import Cura 1.0 as Cura id: customProfileInstantiator model: UM.InstanceContainersModel { - filter: menu.getFilter({ "read_only": false }); + filter: { "type": "quality_changes", "extruder": null, "definition": Cura.MachineManager.filterQualityByMachine ? Cura.MachineManager.activeDefinitionId : "fdmprinter" }; onModelReset: customSeparator.visible = rowCount() > 0 } @@ -76,7 +76,6 @@ import Cura 1.0 as Cura function getFilter(initial_conditions) { var result = initial_conditions; - result.type = "quality" if(Cura.MachineManager.filterQualityByMachine) { diff --git a/resources/qml/Preferences/ProfileTab.qml b/resources/qml/Preferences/ProfileTab.qml new file mode 100644 index 0000000000..72c241babe --- /dev/null +++ b/resources/qml/Preferences/ProfileTab.qml @@ -0,0 +1,38 @@ +// Copyright (c) 2016 Ultimaker B.V. +// Cura is released under the terms of the AGPLv3 or higher. + +import QtQuick 2.1 +import QtQuick.Controls 1.1 + +import UM 1.2 as UM +import Cura 1.0 as Cura + +Tab +{ + id: base + + property string extruderId: ""; + property string quality: ""; + property string material: ""; + + TableView + { + anchors.fill: parent + anchors.margins: UM.Theme.getSize("default_margin").width + + TableViewColumn { role: "label"; title: catalog.i18nc("@title:column", "Setting") } + TableViewColumn { role: "profile_value"; title: catalog.i18nc("@title:column", "Profile Value"); } + TableViewColumn { role: "user_value"; title: catalog.i18nc("@title:column", "User Value"); visible: quality == Cura.MachineManager.activeQualityId } + TableViewColumn { role: "unit"; title: catalog.i18nc("@title:column", "Unit") } + + section.property: "category" + section.delegate: Label { text: section } + + model: Cura.QualitySettingsModel + { + extruderId: base.extruderId != "" ? base.extruderId : null; + quality: base.quality != null ? base.quality : ""; + material: base.material + } + } +} diff --git a/resources/qml/Preferences/ProfilesPage.qml b/resources/qml/Preferences/ProfilesPage.qml index 0ef55a1e37..e612cbc46c 100644 --- a/resources/qml/Preferences/ProfilesPage.qml +++ b/resources/qml/Preferences/ProfilesPage.qml @@ -18,13 +18,13 @@ UM.ManagementPage { filter: { - var result = { "type": "quality" }; + var result = { "type": "quality*", "extruder": null }; if(Cura.MachineManager.filterQualityByMachine) { result.definition = Cura.MachineManager.activeDefinitionId; if(Cura.MachineManager.hasMaterials) { - result.material = Cura.MachineManager.activeMaterialId; + result.material = Cura.MachineManager.allActiveMaterialIds[Cura.MachineManager.activeMachineId]; } } else @@ -76,9 +76,9 @@ UM.ManagementPage { var selectedContainer; if (base.currentItem.id == Cura.MachineManager.activeQualityId) { - selectedContainer = Cura.MachineManager.newQualityContainerFromQualityAndUser(); + selectedContainer = Cura.ContainerManager.createQualityChanges(); } else { - selectedContainer = Cura.MachineManager.duplicateContainer(base.currentItem.id); + selectedContainer = Cura.ContainerManager.duplicateQualityOrQualityChanges(base.currentItem.name); } base.selectContainer(selectedContainer); @@ -106,13 +106,15 @@ UM.ManagementPage text: catalog.i18nc("@action:button", "Import"); iconName: "document-import"; onClicked: importDialog.open(); + enabled: false }, Button { text: catalog.i18nc("@action:button", "Export") iconName: "document-export" onClicked: exportDialog.open() - enabled: currentItem != null +// enabled: currentItem != null + enabled: false } ] @@ -152,14 +154,14 @@ UM.ManagementPage return catalog.i18nc("@action:button", "Update profile with current settings"); } enabled: Cura.MachineManager.hasUserSettings && !Cura.MachineManager.isReadOnly(Cura.MachineManager.activeQualityId) - onClicked: Cura.MachineManager.updateQualityContainerFromUserContainer() + onClicked: Cura.ContainerManager.updateQualityChanges() } Button { text: catalog.i18nc("@action:button", "Discard current settings"); enabled: Cura.MachineManager.hasUserSettings - onClicked: Cura.MachineManager.clearUserSettings(); + onClicked: Cura.ContainerManager.clearUserContainers(); } } @@ -173,7 +175,7 @@ UM.ManagementPage Label { id: defaultsMessage - visible: currentItem && !currentItem.metadata.has_settings + visible: false text: catalog.i18nc("@action:label", "This profile has no settings and uses the defaults specified by the printer.") wrapMode: Text.WordWrap width: parent.width @@ -187,71 +189,31 @@ UM.ManagementPage } } - ScrollView { - id: scrollView - + TabView + { anchors.left: parent.left anchors.top: profileNotices.visible ? profileNotices.bottom : profileNotices.anchors.top anchors.topMargin: UM.Theme.getSize("default_margin").height anchors.right: parent.right anchors.bottom: parent.bottom - ListView { - model: Cura.ContainerSettingsModel + ProfileTab + { + title: catalog.i18nc("@title:tab", "Global Settings"); + quality: base.currentItem != null ? base.currentItem.id : ""; + material: Cura.MachineManager.allActiveMaterialIds.global + } + + Repeater + { + model: Cura.ExtrudersModel { } + + ProfileTab { - containers: - { - if (!currentItem) { - return [] - } else if (currentItem.id == Cura.MachineManager.activeQualityId) { - return [base.currentItem.id, Cura.MachineManager.activeUserProfileId] - } else { - return [base.currentItem.id] - } - } - } - delegate: Row { - property variant setting: model - spacing: UM.Theme.getSize("default_margin").width/2 - Label { - text: model.label - elide: Text.ElideMiddle - width: scrollView.width / 100 * 40 - } - Repeater { - model: setting.values.length - Label { - text: setting.values[index].toString() - width: scrollView.width / 100 * 15 - elide: Text.ElideRight - font.strikeout: index < setting.values.length - 1 && setting.values[index + 1] != "" - opacity: font.strikeout ? 0.5 : 1 - } - } - Label { - text: model.unit - } - } - header: Row { - visible: currentItem && currentItem.id == Cura.MachineManager.activeQualityId - spacing: UM.Theme.getSize("default_margin").width - Label { - text: catalog.i18nc("@action:label", "Profile:") - width: scrollView.width / 100 * 55 - horizontalAlignment: Text.AlignRight - font.bold: true - } - Label { - text: catalog.i18nc("@action:label", "Current:") - visible: currentItem && currentItem.id == Cura.MachineManager.activeQualityId - font.bold: true - } - } - section.property: "category" - section.criteria: ViewSection.FullString - section.delegate: Label { - text: section - font.bold: true + title: model.name; + extruderId: model.id; + quality: base.currentItem != null ? base.currentItem.id : null; + material: Cura.MachineManager.allActiveMaterialIds[model.id] } } } @@ -265,17 +227,25 @@ UM.ManagementPage { id: confirmDialog object: base.currentItem != null ? base.currentItem.name : "" - onYes: Cura.MachineManager.removeQualityContainer(base.currentItem.id) + onYes: + { + var name = base.currentItem.name; + Cura.ContainerManager.removeQualityChanges(name) + if(Cura.MachineManager.activeQualityName == name) + { + Cura.MachineManager.setActiveQuality(base.model.getItem(0).name) + } + } } UM.RenameDialog { id: renameDialog; object: base.currentItem != null ? base.currentItem.name : "" property bool removeWhenRejected: false - onAccepted: Cura.MachineManager.renameQualityContainer(base.currentItem.id, newName) + onAccepted: Cura.ContainerManager.renameQualityChanges(base.currentItem.name, newName) onRejected: { if(removeWhenRejected) { - Cura.MachineManager.removeQualityContainer(base.currentItem.id) + Cura.ContainerManager.removeQualityChanges(base.currentItem.name) } } } diff --git a/resources/qml/Settings/SettingItem.qml b/resources/qml/Settings/SettingItem.qml index dae9953690..a091b55c8b 100644 --- a/resources/qml/Settings/SettingItem.qml +++ b/resources/qml/Settings/SettingItem.qml @@ -27,7 +27,6 @@ Item { // Create properties to put property provider stuff in (bindings break in qt 5.5.1 otherwise) property var state: propertyProvider.properties.state - property var settablePerExtruder: propertyProvider.properties.settable_per_extruder property var stackLevels: propertyProvider.stackLevels property var stackLevel: stackLevels[0] @@ -138,7 +137,7 @@ Item { { id: linkedSettingIcon; - visible: Cura.MachineManager.activeStackId != Cura.MachineManager.activeMachineId && base.settablePerExtruder != "True" && base.showLinkedSettingIcon + visible: Cura.MachineManager.activeStackId != Cura.MachineManager.activeMachineId && !definition.settable_per_extruder && base.showLinkedSettingIcon height: parent.height; width: height; diff --git a/resources/qml/Settings/SettingView.qml b/resources/qml/Settings/SettingView.qml index 978e2dcaed..57cf8f4add 100644 --- a/resources/qml/Settings/SettingView.qml +++ b/resources/qml/Settings/SettingView.qml @@ -94,31 +94,37 @@ ScrollView { target: provider property: "containerStackId" + when: model.settable_per_extruder || model.settable_per_mesh || (inheritStackProvider.properties.global_inherits_stack != null && inheritStackProvider.properties.global_inherits_stack >= 0); value: { - if(inheritStackProvider.properties.global_inherits_stack == -1 || inheritStackProvider.properties.global_inherits_stack == null) + if(!model.settable_per_extruder && !model.settable_per_mesh) { - if( ExtruderManager.activeExtruderStackId) - { - return ExtruderManager.activeExtruderStackId - } - else - { - return Cura.MachineManager.activeMachineId - } + //Not settable per extruder, so we must pick global. + return Cura.MachineManager.activeMachineId; } - return ExtruderManager.extruderIds[String(inheritStackProvider.properties.global_inherits_stack)] + if(inheritStackProvider.properties.global_inherits_stack != null && inheritStackProvider.properties.global_inherits_stack >= 0) + { + //We have global_inherits_stack, so pick that stack. + return ExtruderManager.extruderIds[String(inheritStackProvider.properties.global_inherits_stack)]; + } + if(ExtruderManager.activeExtruderStackId) + { + //We're on an extruder tab. Pick the current extruder. + return ExtruderManager.activeExtruderStackId; + } + //No extruder tab is selected. Pick the global stack. Shouldn't happen any more since we removed the global tab. + return Cura.MachineManager.activeMachineId; } } // Specialty provider that only watches global_inherits (we cant filter on what property changed we get events - // so we bypass that to make a dedicated provider. + // so we bypass that to make a dedicated provider). UM.SettingPropertyProvider { id: inheritStackProvider containerStackId: Cura.MachineManager.activeMachineId key: model.key - watchedProperties: [ "global_inherits_stack"] + watchedProperties: [ "global_inherits_stack" ] } UM.SettingPropertyProvider @@ -127,7 +133,7 @@ ScrollView containerStackId: Cura.MachineManager.activeMachineId key: model.key ? model.key : "" - watchedProperties: [ "value", "enabled", "state", "validationState", "settable_per_extruder" ] + watchedProperties: [ "value", "enabled", "state", "validationState" ] storeIndex: 0 } diff --git a/resources/quality/high.inst.cfg b/resources/quality/high.inst.cfg index b4498c6c8b..ec3ab18fd6 100644 --- a/resources/quality/high.inst.cfg +++ b/resources/quality/high.inst.cfg @@ -5,6 +5,7 @@ definition = fdmprinter [metadata] type = quality +quality_type = high weight = -3 [values] diff --git a/resources/quality/low.inst.cfg b/resources/quality/low.inst.cfg index d34a7c6461..787325c27c 100644 --- a/resources/quality/low.inst.cfg +++ b/resources/quality/low.inst.cfg @@ -5,6 +5,7 @@ definition = fdmprinter [metadata] type = quality +quality_type = low weight = -1 [values] diff --git a/resources/quality/normal.inst.cfg b/resources/quality/normal.inst.cfg index 417c7c700f..cfd70de49c 100644 --- a/resources/quality/normal.inst.cfg +++ b/resources/quality/normal.inst.cfg @@ -5,6 +5,7 @@ definition = fdmprinter [metadata] type = quality +quality_type = normal weight = -2 [values] diff --git a/resources/quality/ultimaker2_extended_plus/um2ep_abs_0.25_normal.inst.cfg b/resources/quality/ultimaker2_extended_plus/um2ep_abs_0.25_normal.inst.cfg index 11b926378d..2d0a81c8a4 100644 --- a/resources/quality/ultimaker2_extended_plus/um2ep_abs_0.25_normal.inst.cfg +++ b/resources/quality/ultimaker2_extended_plus/um2ep_abs_0.25_normal.inst.cfg @@ -7,6 +7,7 @@ definition = ultimaker2_extended_plus type = quality material = generic_abs_ultimaker2_extended_plus_0.25_mm weight = -2 +quality_type = high [values] layer_height = 0.06 diff --git a/resources/quality/ultimaker2_extended_plus/um2ep_abs_0.4_fast.inst.cfg b/resources/quality/ultimaker2_extended_plus/um2ep_abs_0.4_fast.inst.cfg index bdeeb935f4..a882429f2a 100644 --- a/resources/quality/ultimaker2_extended_plus/um2ep_abs_0.4_fast.inst.cfg +++ b/resources/quality/ultimaker2_extended_plus/um2ep_abs_0.4_fast.inst.cfg @@ -7,6 +7,7 @@ definition = ultimaker2_extended_plus type = quality material = generic_abs_ultimaker2_extended_plus_0.4_mm weight = -1 +quality_type = fast [values] layer_height = 0.15 diff --git a/resources/quality/ultimaker2_extended_plus/um2ep_abs_0.4_high.inst.cfg b/resources/quality/ultimaker2_extended_plus/um2ep_abs_0.4_high.inst.cfg index d658ee5bb5..5650353f7a 100644 --- a/resources/quality/ultimaker2_extended_plus/um2ep_abs_0.4_high.inst.cfg +++ b/resources/quality/ultimaker2_extended_plus/um2ep_abs_0.4_high.inst.cfg @@ -7,6 +7,7 @@ definition = ultimaker2_extended_plus type = quality material = generic_abs_ultimaker2_extended_plus_0.4_mm weight = -3 +quality_type = high [values] layer_height = 0.06 diff --git a/resources/quality/ultimaker2_extended_plus/um2ep_abs_0.4_normal.inst.cfg b/resources/quality/ultimaker2_extended_plus/um2ep_abs_0.4_normal.inst.cfg index ff024ccc69..6b5901ad15 100644 --- a/resources/quality/ultimaker2_extended_plus/um2ep_abs_0.4_normal.inst.cfg +++ b/resources/quality/ultimaker2_extended_plus/um2ep_abs_0.4_normal.inst.cfg @@ -7,6 +7,7 @@ definition = ultimaker2_extended_plus type = quality material = generic_abs_ultimaker2_extended_plus_0.4_mm weight = -2 +quality_type = normal [values] layer_height = 0.1 diff --git a/resources/quality/ultimaker2_extended_plus/um2ep_abs_0.6_normal.inst.cfg b/resources/quality/ultimaker2_extended_plus/um2ep_abs_0.6_normal.inst.cfg index c2f4daa86f..bcc2f29656 100644 --- a/resources/quality/ultimaker2_extended_plus/um2ep_abs_0.6_normal.inst.cfg +++ b/resources/quality/ultimaker2_extended_plus/um2ep_abs_0.6_normal.inst.cfg @@ -7,6 +7,7 @@ definition = ultimaker2_extended_plus type = quality material = generic_abs_ultimaker2_extended_plus_0.6_mm weight = -2 +quality_type = normal [values] layer_height = 0.15 diff --git a/resources/quality/ultimaker2_extended_plus/um2ep_abs_0.8_normal.inst.cfg b/resources/quality/ultimaker2_extended_plus/um2ep_abs_0.8_normal.inst.cfg index 362e844214..3fea836f7a 100644 --- a/resources/quality/ultimaker2_extended_plus/um2ep_abs_0.8_normal.inst.cfg +++ b/resources/quality/ultimaker2_extended_plus/um2ep_abs_0.8_normal.inst.cfg @@ -7,6 +7,7 @@ definition = ultimaker2_extended_plus type = quality material = generic_abs_ultimaker2_extended_plus_0.8_mm weight = -2 +quality_type = fast [values] layer_height = 0.2 diff --git a/resources/quality/ultimaker2_extended_plus/um2ep_cpe_0.25_normal.inst.cfg b/resources/quality/ultimaker2_extended_plus/um2ep_cpe_0.25_normal.inst.cfg index f4d9264d3e..7774ba3534 100644 --- a/resources/quality/ultimaker2_extended_plus/um2ep_cpe_0.25_normal.inst.cfg +++ b/resources/quality/ultimaker2_extended_plus/um2ep_cpe_0.25_normal.inst.cfg @@ -7,6 +7,7 @@ definition = ultimaker2_extended_plus type = quality material = generic_cpe_ultimaker2_extended_plus_0.25_mm weight = -2 +quality_type = high [values] layer_height = 0.06 diff --git a/resources/quality/ultimaker2_extended_plus/um2ep_cpe_0.4_fast.inst.cfg b/resources/quality/ultimaker2_extended_plus/um2ep_cpe_0.4_fast.inst.cfg index f514f22294..256c304149 100644 --- a/resources/quality/ultimaker2_extended_plus/um2ep_cpe_0.4_fast.inst.cfg +++ b/resources/quality/ultimaker2_extended_plus/um2ep_cpe_0.4_fast.inst.cfg @@ -7,6 +7,7 @@ definition = ultimaker2_extended_plus type = quality material = generic_cpe_ultimaker2_extended_plus_0.4_mm weight = -1 +quality_type = fast [values] layer_height = 0.15 diff --git a/resources/quality/ultimaker2_extended_plus/um2ep_cpe_0.4_high.inst.cfg b/resources/quality/ultimaker2_extended_plus/um2ep_cpe_0.4_high.inst.cfg index 0c68be2f5f..0c70fe615d 100644 --- a/resources/quality/ultimaker2_extended_plus/um2ep_cpe_0.4_high.inst.cfg +++ b/resources/quality/ultimaker2_extended_plus/um2ep_cpe_0.4_high.inst.cfg @@ -7,6 +7,7 @@ definition = ultimaker2_extended_plus type = quality material = generic_cpe_ultimaker2_extended_plus_0.4_mm weight = -3 +quality_type = high [values] layer_height = 0.06 diff --git a/resources/quality/ultimaker2_extended_plus/um2ep_cpe_0.4_normal.inst.cfg b/resources/quality/ultimaker2_extended_plus/um2ep_cpe_0.4_normal.inst.cfg index 26ea8ce9bc..541ea1b468 100644 --- a/resources/quality/ultimaker2_extended_plus/um2ep_cpe_0.4_normal.inst.cfg +++ b/resources/quality/ultimaker2_extended_plus/um2ep_cpe_0.4_normal.inst.cfg @@ -7,6 +7,7 @@ definition = ultimaker2_extended_plus type = quality material = generic_cpe_ultimaker2_extended_plus_0.4_mm weight = -2 +quality_type = normal [values] layer_height = 0.1 diff --git a/resources/quality/ultimaker2_extended_plus/um2ep_cpe_0.6_normal.inst.cfg b/resources/quality/ultimaker2_extended_plus/um2ep_cpe_0.6_normal.inst.cfg index d6d10dbe1a..09e9ec2941 100644 --- a/resources/quality/ultimaker2_extended_plus/um2ep_cpe_0.6_normal.inst.cfg +++ b/resources/quality/ultimaker2_extended_plus/um2ep_cpe_0.6_normal.inst.cfg @@ -7,6 +7,7 @@ definition = ultimaker2_extended_plus type = quality material = generic_cpe_ultimaker2_extended_plus_0.6_mm weight = -2 +quality_type = normal [values] layer_height = 0.15 diff --git a/resources/quality/ultimaker2_extended_plus/um2ep_cpe_0.8_normal.inst.cfg b/resources/quality/ultimaker2_extended_plus/um2ep_cpe_0.8_normal.inst.cfg index 53d5e0bc8c..e3d8d5462f 100644 --- a/resources/quality/ultimaker2_extended_plus/um2ep_cpe_0.8_normal.inst.cfg +++ b/resources/quality/ultimaker2_extended_plus/um2ep_cpe_0.8_normal.inst.cfg @@ -7,6 +7,7 @@ definition = ultimaker2_extended_plus type = quality material = generic_cpe_ultimaker2_extended_plus_0.8_mm weight = -2 +quality_type = fast [values] layer_height = 0.2 diff --git a/resources/quality/ultimaker2_extended_plus/um2ep_pla_0.25_normal.inst.cfg b/resources/quality/ultimaker2_extended_plus/um2ep_pla_0.25_normal.inst.cfg index 5e54b3194a..346df10c44 100644 --- a/resources/quality/ultimaker2_extended_plus/um2ep_pla_0.25_normal.inst.cfg +++ b/resources/quality/ultimaker2_extended_plus/um2ep_pla_0.25_normal.inst.cfg @@ -7,6 +7,7 @@ definition = ultimaker2_extended_plus type = quality material = generic_pla_ultimaker2_extended_plus_0.25_mm weight = -2 +quality_type = high [values] layer_height = 0.06 diff --git a/resources/quality/ultimaker2_extended_plus/um2ep_pla_0.4_fast.inst.cfg b/resources/quality/ultimaker2_extended_plus/um2ep_pla_0.4_fast.inst.cfg index 893256bb33..7bba3a504d 100644 --- a/resources/quality/ultimaker2_extended_plus/um2ep_pla_0.4_fast.inst.cfg +++ b/resources/quality/ultimaker2_extended_plus/um2ep_pla_0.4_fast.inst.cfg @@ -7,6 +7,7 @@ definition = ultimaker2_extended_plus type = quality material = generic_pla_ultimaker2_extended_plus_0.4_mm weight = -1 +quality_type = fast [values] layer_height = 0.15 diff --git a/resources/quality/ultimaker2_extended_plus/um2ep_pla_0.4_high.inst.cfg b/resources/quality/ultimaker2_extended_plus/um2ep_pla_0.4_high.inst.cfg index 844e2b3eac..939d099d55 100644 --- a/resources/quality/ultimaker2_extended_plus/um2ep_pla_0.4_high.inst.cfg +++ b/resources/quality/ultimaker2_extended_plus/um2ep_pla_0.4_high.inst.cfg @@ -7,6 +7,7 @@ definition = ultimaker2_extended_plus type = quality material = generic_pla_ultimaker2_extended_plus_0.4_mm weight = -3 +quality_type = high [values] layer_height = 0.06 diff --git a/resources/quality/ultimaker2_extended_plus/um2ep_pla_0.4_normal.inst.cfg b/resources/quality/ultimaker2_extended_plus/um2ep_pla_0.4_normal.inst.cfg index 47d511446a..7e521e8fe8 100644 --- a/resources/quality/ultimaker2_extended_plus/um2ep_pla_0.4_normal.inst.cfg +++ b/resources/quality/ultimaker2_extended_plus/um2ep_pla_0.4_normal.inst.cfg @@ -7,6 +7,7 @@ definition = ultimaker2_extended_plus type = quality material = generic_pla_ultimaker2_extended_plus_0.4_mm weight = -2 +quality_type = normal [values] layer_height = 0.1 diff --git a/resources/quality/ultimaker2_extended_plus/um2ep_pla_0.6_normal.inst.cfg b/resources/quality/ultimaker2_extended_plus/um2ep_pla_0.6_normal.inst.cfg index a2b15b6f16..0745ed891f 100644 --- a/resources/quality/ultimaker2_extended_plus/um2ep_pla_0.6_normal.inst.cfg +++ b/resources/quality/ultimaker2_extended_plus/um2ep_pla_0.6_normal.inst.cfg @@ -7,6 +7,7 @@ definition = ultimaker2_extended_plus material = generic_pla_ultimaker2_extended_plus_0.6_mm type = quality weight = -2 +quality_type = normal [values] layer_height = 0.15 diff --git a/resources/quality/ultimaker2_extended_plus/um2ep_pla_0.8_normal.inst.cfg b/resources/quality/ultimaker2_extended_plus/um2ep_pla_0.8_normal.inst.cfg index 08b5bec667..f5f66dce6c 100644 --- a/resources/quality/ultimaker2_extended_plus/um2ep_pla_0.8_normal.inst.cfg +++ b/resources/quality/ultimaker2_extended_plus/um2ep_pla_0.8_normal.inst.cfg @@ -7,6 +7,7 @@ definition = ultimaker2_extended_plus material = generic_pla_ultimaker2_extended_plus_0.8_mm type = quality weight = -2 +quality_type = fast [values] layer_height = 0.2 diff --git a/resources/quality/ultimaker2_plus/pla_0.25_normal.inst.cfg b/resources/quality/ultimaker2_plus/pla_0.25_normal.inst.cfg index 9a44582610..18d74386cf 100644 --- a/resources/quality/ultimaker2_plus/pla_0.25_normal.inst.cfg +++ b/resources/quality/ultimaker2_plus/pla_0.25_normal.inst.cfg @@ -7,6 +7,7 @@ definition = ultimaker2_plus type = quality material = generic_pla_ultimaker2_plus_0.25_mm weight = -2 +quality_type = high [values] layer_height = 0.06 diff --git a/resources/quality/ultimaker2_plus/pla_0.4_fast.inst.cfg b/resources/quality/ultimaker2_plus/pla_0.4_fast.inst.cfg index 0df882e418..b17a1f2a6a 100644 --- a/resources/quality/ultimaker2_plus/pla_0.4_fast.inst.cfg +++ b/resources/quality/ultimaker2_plus/pla_0.4_fast.inst.cfg @@ -7,6 +7,7 @@ definition = ultimaker2_plus type = quality material = generic_pla_ultimaker2_plus_0.4_mm weight = -1 +quality_type = fast [values] layer_height = 0.15 diff --git a/resources/quality/ultimaker2_plus/pla_0.4_high.inst.cfg b/resources/quality/ultimaker2_plus/pla_0.4_high.inst.cfg index a8abdb081f..ff542c7c19 100644 --- a/resources/quality/ultimaker2_plus/pla_0.4_high.inst.cfg +++ b/resources/quality/ultimaker2_plus/pla_0.4_high.inst.cfg @@ -7,6 +7,7 @@ definition = ultimaker2_plus type = quality material = generic_pla_ultimaker2_plus_0.4_mm weight = -3 +quality_type = high [values] layer_height = 0.06 diff --git a/resources/quality/ultimaker2_plus/pla_0.4_normal.inst.cfg b/resources/quality/ultimaker2_plus/pla_0.4_normal.inst.cfg index c29b017bbe..79d868f25f 100644 --- a/resources/quality/ultimaker2_plus/pla_0.4_normal.inst.cfg +++ b/resources/quality/ultimaker2_plus/pla_0.4_normal.inst.cfg @@ -7,6 +7,7 @@ definition = ultimaker2_plus type = quality material = generic_pla_ultimaker2_plus_0.4_mm weight = -2 +quality_type = normal [values] layer_height = 0.1 diff --git a/resources/quality/ultimaker2_plus/pla_0.6_normal.inst.cfg b/resources/quality/ultimaker2_plus/pla_0.6_normal.inst.cfg index 5a0a840ae7..63beca8fbb 100644 --- a/resources/quality/ultimaker2_plus/pla_0.6_normal.inst.cfg +++ b/resources/quality/ultimaker2_plus/pla_0.6_normal.inst.cfg @@ -7,6 +7,7 @@ definition = ultimaker2_plus material = generic_pla_ultimaker2_plus_0.6_mm type = quality weight = -2 +quality_type = normal [values] layer_height = 0.15 diff --git a/resources/quality/ultimaker2_plus/pla_0.8_normal.inst.cfg b/resources/quality/ultimaker2_plus/pla_0.8_normal.inst.cfg index bd90b8c059..f2b78846a8 100644 --- a/resources/quality/ultimaker2_plus/pla_0.8_normal.inst.cfg +++ b/resources/quality/ultimaker2_plus/pla_0.8_normal.inst.cfg @@ -7,6 +7,7 @@ definition = ultimaker2_plus material = generic_pla_ultimaker2_plus_0.8_mm type = quality weight = -2 +quality_type = fast [values] layer_height = 0.2 diff --git a/resources/quality/ultimaker2_plus/um2p_abs_0.25_normal.inst.cfg b/resources/quality/ultimaker2_plus/um2p_abs_0.25_normal.inst.cfg index 05a9bce71c..8457d5cd2b 100644 --- a/resources/quality/ultimaker2_plus/um2p_abs_0.25_normal.inst.cfg +++ b/resources/quality/ultimaker2_plus/um2p_abs_0.25_normal.inst.cfg @@ -7,6 +7,7 @@ definition = ultimaker2_plus type = quality material = generic_abs_ultimaker2_plus_0.25_mm weight = -2 +quality_type = high [values] layer_height = 0.06 diff --git a/resources/quality/ultimaker2_plus/um2p_abs_0.4_fast.inst.cfg b/resources/quality/ultimaker2_plus/um2p_abs_0.4_fast.inst.cfg index cd0a25981a..8bcb3efee4 100644 --- a/resources/quality/ultimaker2_plus/um2p_abs_0.4_fast.inst.cfg +++ b/resources/quality/ultimaker2_plus/um2p_abs_0.4_fast.inst.cfg @@ -7,6 +7,7 @@ definition = ultimaker2_plus type = quality material = generic_abs_ultimaker2_plus_0.4_mm weight = -1 +quality_type = fast [values] layer_height = 0.15 diff --git a/resources/quality/ultimaker2_plus/um2p_abs_0.4_high.inst.cfg b/resources/quality/ultimaker2_plus/um2p_abs_0.4_high.inst.cfg index 4b1ece31ef..f2235abd41 100644 --- a/resources/quality/ultimaker2_plus/um2p_abs_0.4_high.inst.cfg +++ b/resources/quality/ultimaker2_plus/um2p_abs_0.4_high.inst.cfg @@ -7,6 +7,7 @@ definition = ultimaker2_plus type = quality material = generic_abs_ultimaker2_plus_0.4_mm weight = -3 +quality_type = high [values] layer_height = 0.06 diff --git a/resources/quality/ultimaker2_plus/um2p_abs_0.4_normal.inst.cfg b/resources/quality/ultimaker2_plus/um2p_abs_0.4_normal.inst.cfg index f1b01fd408..1b8c1035db 100644 --- a/resources/quality/ultimaker2_plus/um2p_abs_0.4_normal.inst.cfg +++ b/resources/quality/ultimaker2_plus/um2p_abs_0.4_normal.inst.cfg @@ -7,6 +7,7 @@ definition = ultimaker2_plus type = quality material = generic_abs_ultimaker2_plus_0.4_mm weight = -2 +quality_type = normal [values] layer_height = 0.1 diff --git a/resources/quality/ultimaker2_plus/um2p_abs_0.6_normal.inst.cfg b/resources/quality/ultimaker2_plus/um2p_abs_0.6_normal.inst.cfg index 89e73dda38..4ef0f34484 100644 --- a/resources/quality/ultimaker2_plus/um2p_abs_0.6_normal.inst.cfg +++ b/resources/quality/ultimaker2_plus/um2p_abs_0.6_normal.inst.cfg @@ -7,6 +7,7 @@ definition = ultimaker2_plus type = quality material = generic_abs_ultimaker2_plus_0.6_mm weight = -2 +quality_type = normal [values] layer_height = 0.15 diff --git a/resources/quality/ultimaker2_plus/um2p_abs_0.8_normal.inst.cfg b/resources/quality/ultimaker2_plus/um2p_abs_0.8_normal.inst.cfg index 2171fd3837..ca2f736c01 100644 --- a/resources/quality/ultimaker2_plus/um2p_abs_0.8_normal.inst.cfg +++ b/resources/quality/ultimaker2_plus/um2p_abs_0.8_normal.inst.cfg @@ -7,6 +7,7 @@ definition = ultimaker2_plus type = quality material = generic_abs_ultimaker2_plus_0.8_mm weight = -2 +quality_type = fast [values] layer_height = 0.2 diff --git a/resources/quality/ultimaker2_plus/um2p_cpe_0.25_normal.inst.cfg b/resources/quality/ultimaker2_plus/um2p_cpe_0.25_normal.inst.cfg index 6a300ba27d..0f2a612619 100644 --- a/resources/quality/ultimaker2_plus/um2p_cpe_0.25_normal.inst.cfg +++ b/resources/quality/ultimaker2_plus/um2p_cpe_0.25_normal.inst.cfg @@ -7,6 +7,7 @@ definition = ultimaker2_plus type = quality material = generic_cpe_ultimaker2_plus_0.25_mm weight = -2 +quality_type = high [values] layer_height = 0.06 diff --git a/resources/quality/ultimaker2_plus/um2p_cpe_0.4_fast.inst.cfg b/resources/quality/ultimaker2_plus/um2p_cpe_0.4_fast.inst.cfg index e76c5205f5..8f8fb9e01b 100644 --- a/resources/quality/ultimaker2_plus/um2p_cpe_0.4_fast.inst.cfg +++ b/resources/quality/ultimaker2_plus/um2p_cpe_0.4_fast.inst.cfg @@ -7,6 +7,7 @@ definition = ultimaker2_plus type = quality material = generic_cpe_ultimaker2_plus_0.4_mm weight = -1 +quality_type = fast [values] layer_height = 0.15 diff --git a/resources/quality/ultimaker2_plus/um2p_cpe_0.4_high.inst.cfg b/resources/quality/ultimaker2_plus/um2p_cpe_0.4_high.inst.cfg index 60f171dc17..abc5e562f7 100644 --- a/resources/quality/ultimaker2_plus/um2p_cpe_0.4_high.inst.cfg +++ b/resources/quality/ultimaker2_plus/um2p_cpe_0.4_high.inst.cfg @@ -7,6 +7,7 @@ definition = ultimaker2_plus type = quality material = generic_cpe_ultimaker2_plus_0.4_mm weight = -3 +quality_type = high [values] layer_height = 0.06 diff --git a/resources/quality/ultimaker2_plus/um2p_cpe_0.4_normal.inst.cfg b/resources/quality/ultimaker2_plus/um2p_cpe_0.4_normal.inst.cfg index 04116dbe21..5531f245f0 100644 --- a/resources/quality/ultimaker2_plus/um2p_cpe_0.4_normal.inst.cfg +++ b/resources/quality/ultimaker2_plus/um2p_cpe_0.4_normal.inst.cfg @@ -7,6 +7,7 @@ definition = ultimaker2_plus type = quality material = generic_cpe_ultimaker2_plus_0.4_mm weight = -2 +quality_type = normal [values] layer_height = 0.1 diff --git a/resources/quality/ultimaker2_plus/um2p_cpe_0.6_normal.inst.cfg b/resources/quality/ultimaker2_plus/um2p_cpe_0.6_normal.inst.cfg index 35e666e6d9..3765f98709 100644 --- a/resources/quality/ultimaker2_plus/um2p_cpe_0.6_normal.inst.cfg +++ b/resources/quality/ultimaker2_plus/um2p_cpe_0.6_normal.inst.cfg @@ -7,6 +7,7 @@ definition = ultimaker2_plus type = quality material = generic_cpe_ultimaker2_plus_0.6_mm weight = -2 +quality_type = normal [values] layer_height = 0.15 diff --git a/resources/quality/ultimaker2_plus/um2p_cpe_0.8_normal.inst.cfg b/resources/quality/ultimaker2_plus/um2p_cpe_0.8_normal.inst.cfg index c36d1714a0..179b554973 100644 --- a/resources/quality/ultimaker2_plus/um2p_cpe_0.8_normal.inst.cfg +++ b/resources/quality/ultimaker2_plus/um2p_cpe_0.8_normal.inst.cfg @@ -7,6 +7,7 @@ definition = ultimaker2_plus type = quality material = generic_cpe_ultimaker2_plus_0.8_mm weight = -2 +quality_type = fast [values] layer_height = 0.2