Merge branch 'feature_quality_changes'

This commit is contained in:
Ghostkeeper 2016-08-22 15:13:27 +02:00
commit bb90c593b9
52 changed files with 747 additions and 346 deletions

View file

@ -85,10 +85,10 @@ class CuraApplication(QtApplication):
self._open_file_queue = [] # Files to open when plug-ins are loaded. self._open_file_queue = [] # Files to open when plug-ins are loaded.
# Need to do this before ContainerRegistry tries to load the machines # Need to do this before ContainerRegistry tries to load the machines
SettingDefinition.addSupportedProperty("settable_per_mesh", 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) SettingDefinition.addSupportedProperty("settable_per_extruder", DefinitionPropertyType.Any, default = True, read_only = True)
SettingDefinition.addSupportedProperty("settable_per_meshgroup", DefinitionPropertyType.Any, default = True) SettingDefinition.addSupportedProperty("settable_per_meshgroup", DefinitionPropertyType.Any, default = True, read_only = True)
SettingDefinition.addSupportedProperty("settable_globally", DefinitionPropertyType.Any, default = True) SettingDefinition.addSupportedProperty("settable_globally", DefinitionPropertyType.Any, default = True, read_only = True)
SettingDefinition.addSupportedProperty("global_inherits_stack", DefinitionPropertyType.Function, default = "-1") SettingDefinition.addSupportedProperty("global_inherits_stack", DefinitionPropertyType.Function, default = "-1")
SettingDefinition.addSettingType("extruder", None, str, Validator) SettingDefinition.addSettingType("extruder", None, str, Validator)
@ -182,6 +182,10 @@ class CuraApplication(QtApplication):
empty_quality_container._id = "empty_quality" empty_quality_container._id = "empty_quality"
empty_quality_container.addMetaDataEntry("type", "quality") empty_quality_container.addMetaDataEntry("type", "quality")
ContainerRegistry.getInstance().addContainer(empty_quality_container) 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() ContainerRegistry.getInstance().load()
@ -308,7 +312,7 @@ class CuraApplication(QtApplication):
path = None path = None
if instance_type == "material": if instance_type == "material":
path = Resources.getStoragePath(self.ResourceTypes.MaterialInstanceContainer, file_name) 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) path = Resources.getStoragePath(self.ResourceTypes.QualityInstanceContainer, file_name)
elif instance_type == "user": elif instance_type == "user":
path = Resources.getStoragePath(self.ResourceTypes.UserInstanceContainer, file_name) 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.ContainerSettingsModel, "Cura", 1, 0, "ContainerSettingsModel")
qmlRegisterType(cura.Settings.MaterialSettingsVisibilityHandler, "Cura", 1, 0, "MaterialSettingsVisibilityHandler") 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) qmlRegisterSingletonType(cura.Settings.ContainerManager, "Cura", 1, 0, "ContainerManager", cura.Settings.ContainerManager.createContainerManager)

View file

@ -14,6 +14,8 @@ import UM.Platform
import UM.MimeTypeDatabase import UM.MimeTypeDatabase
import UM.Logger import UM.Logger
import cura.Settings
from UM.MimeTypeDatabase import MimeTypeNotFoundError from UM.MimeTypeDatabase import MimeTypeNotFoundError
from UM.i18n import i18nCatalog from UM.i18n import i18nCatalog
@ -135,12 +137,11 @@ class ContainerManager(QObject):
merge = containers[0] 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") UM.Logger.log("w", "Cannot merge two containers of different types")
return False return False
for key in merge.getAllKeys(): self._performMerge(merge_into, merge)
merge_into.setProperty(key, "value", merge.getProperty(key, "value"))
return True return True
@ -350,6 +351,188 @@ class ContainerManager(QObject):
return { "status": "success", "message": "Successfully imported container {0}".format(container.getName()) } 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): def _updateContainerNameFilters(self):
self._container_name_filters = {} self._container_name_filters = {}
for plugin_id, container_type in UM.Settings.ContainerRegistry.getContainerTypes(): 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) name_filter = "{0} ({1})".format(mime_type.comment, suffix_list)
self._container_name_filters[name_filter] = entry self._container_name_filters[name_filter] = entry
# Factory function, used by QML ## Return a generator that iterates over a set of containers that are filtered by machine and material when needed.
@staticmethod #
def createContainerManager(engine, js_engine): # \param kwargs Initial search criteria that the containers need to match.
return ContainerManager() #
# \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

View file

@ -235,6 +235,9 @@ class ExtruderManager(QObject):
container_stack.addContainer(quality) 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) user_profile = container_registry.findInstanceContainers(type = "user", extruder = extruder_stack_id)
if user_profile: # There was already a user profile, loaded from settings. if user_profile: # There was already a user profile, loaded from settings.
user_profile = user_profile[0] user_profile = user_profile[0]
@ -274,6 +277,20 @@ class ExtruderManager(QObject):
for name in self._extruder_trains[machine_id]: for name in self._extruder_trains[machine_id]:
yield self._extruder_trains[machine_id][name] 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): def __globalContainerStackChanged(self):
self._addCurrentMachineExtruders() self._addCurrentMachineExtruders()
self.activeExtruderChanged.emit() self.activeExtruderChanged.emit()

View file

@ -26,16 +26,17 @@ class MachineManager(QObject):
self._global_container_stack = None self._global_container_stack = None
Application.getInstance().globalContainerStackChanged.connect(self._onGlobalContainerChanged) 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._active_stack_valid = None
self._onGlobalContainerChanged() self._onGlobalContainerChanged()
ExtruderManager.getInstance().activeExtruderChanged.connect(self._onActiveExtruderStackChanged) ExtruderManager.getInstance().activeExtruderChanged.connect(self._onActiveExtruderStackChanged)
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.activeMaterialChanged)
ExtruderManager.getInstance().activeExtruderChanged.connect(self.activeVariantChanged) ExtruderManager.getInstance().activeExtruderChanged.connect(self.activeVariantChanged)
ExtruderManager.getInstance().activeExtruderChanged.connect(self.activeQualityChanged) 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_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_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_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", "") Preferences.getInstance().addPreference("cura/active_machine", "")
@ -184,107 +186,11 @@ class MachineManager(QObject):
if old_index is not None: if old_index is not None:
extruder_manager.setActiveExtruderIndex(old_index) 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): def _onGlobalContainerChanged(self):
if self._global_container_stack: if self._global_container_stack:
self._global_container_stack.nameChanged.disconnect(self._onMachineNameChanged) self._global_container_stack.nameChanged.disconnect(self._onMachineNameChanged)
self._global_container_stack.containersChanged.disconnect(self._onInstanceContainersChanged) 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 = self._global_container_stack.findContainer({"type": "material"})
material.nameChanged.disconnect(self._onMaterialNameChanged) material.nameChanged.disconnect(self._onMaterialNameChanged)
@ -301,7 +207,7 @@ class MachineManager(QObject):
Preferences.getInstance().setValue("cura/active_machine", self._global_container_stack.getId()) Preferences.getInstance().setValue("cura/active_machine", self._global_container_stack.getId())
self._global_container_stack.nameChanged.connect(self._onMachineNameChanged) self._global_container_stack.nameChanged.connect(self._onMachineNameChanged)
self._global_container_stack.containersChanged.connect(self._onInstanceContainersChanged) 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 = self._global_container_stack.findContainer({"type": "material"})
material.nameChanged.connect(self._onMaterialNameChanged) material.nameChanged.connect(self._onMaterialNameChanged)
@ -312,11 +218,11 @@ class MachineManager(QObject):
self.blurSettings.emit() # Ensure no-one has focus. self.blurSettings.emit() # Ensure no-one has focus.
if self._active_container_stack and self._active_container_stack != self._global_container_stack: 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.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() self._active_container_stack = ExtruderManager.getInstance().getActiveExtruderStack()
if self._active_container_stack: if self._active_container_stack:
self._active_container_stack.containersChanged.connect(self._onInstanceContainersChanged) 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: else:
self._active_container_stack = self._global_container_stack self._active_container_stack = self._global_container_stack
self._active_stack_valid = not self._checkStackForErrors(self._active_container_stack) self._active_stack_valid = not self._checkStackForErrors(self._active_container_stack)
@ -325,17 +231,6 @@ class MachineManager(QObject):
def _onInstanceContainersChanged(self, container): def _onInstanceContainersChanged(self, container):
container_type = container.getMetaDataEntry("type") 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": if container_type == "material":
self.activeMaterialChanged.emit() self.activeMaterialChanged.emit()
elif container_type == "variant": elif container_type == "variant":
@ -343,6 +238,23 @@ class MachineManager(QObject):
elif container_type == "quality": elif container_type == "quality":
self.activeQualityChanged.emit() 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) @pyqtSlot(str)
def setActiveMachine(self, stack_id): def setActiveMachine(self, stack_id):
containers = UM.Settings.ContainerRegistry.getInstance().findContainerStacks(id = 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]) current_settings_instance_container.setDefinition(definitions[0])
container_registry.addContainer(current_settings_instance_container) 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) new_global_stack.addContainer(definition)
if variant_instance_container: if variant_instance_container:
new_global_stack.addContainer(variant_instance_container) new_global_stack.addContainer(variant_instance_container)
@ -378,6 +289,8 @@ class MachineManager(QObject):
new_global_stack.addContainer(material_instance_container) new_global_stack.addContainer(material_instance_container)
if quality_instance_container: if quality_instance_container:
new_global_stack.addContainer(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) new_global_stack.addContainer(current_settings_instance_container)
ExtruderManager.getInstance().addMachineExtruders(definition, new_global_stack.getId()) 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 ## Check if the global_container has instances in the user container
@pyqtProperty(bool, notify = activeStackChanged) @pyqtProperty(bool, notify = activeStackChanged)
def hasUserSettings(self): def hasUserSettings(self):
if not self._active_container_stack: if not self._global_container_stack:
return False return False
user_settings = self._active_container_stack.getTop().findInstances(**{}) if self._global_container_stack.getTop().findInstances():
return len(user_settings) != 0 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 ## Check if the global profile does not contain error states
# Note that the _active_stack_valid is cached due to performance issues # Note that the _active_stack_valid is cached due to performance issues
@ -477,6 +396,22 @@ class MachineManager(QObject):
return "" 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) @pyqtProperty(str, notify=activeQualityChanged)
def activeQualityMaterialId(self): def activeQualityMaterialId(self):
if self._active_container_stack: if self._active_container_stack:
@ -489,6 +424,9 @@ class MachineManager(QObject):
@pyqtProperty(str, notify=activeQualityChanged) @pyqtProperty(str, notify=activeQualityChanged)
def activeQualityName(self): def activeQualityName(self):
if self._active_container_stack: 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"}) quality = self._active_container_stack.findContainer({"type": "quality"})
if quality: if quality:
return quality.getName() return quality.getName()
@ -496,12 +434,31 @@ class MachineManager(QObject):
@pyqtProperty(str, notify=activeQualityChanged) @pyqtProperty(str, notify=activeQualityChanged)
def activeQualityId(self): def activeQualityId(self):
if self._active_container_stack: if self._global_container_stack:
quality = self._active_container_stack.findContainer({"type": "quality"}) 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: if quality:
return quality.getId() return quality.getId()
return "" 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 ## Check if a container is read_only
@pyqtSlot(str, result = bool) @pyqtSlot(str, result = bool)
def isReadOnly(self, container_id): 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: if extruder_stack != self._active_container_stack and extruder_stack.getProperty(key, "value") != new_value:
extruder_stack.getTop().setProperty(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) @pyqtSlot(str)
def setActiveMaterial(self, material_id): def setActiveMaterial(self, material_id):
containers = UM.Settings.ContainerRegistry.getInstance().findInstanceContainers(id = material_id) containers = UM.Settings.ContainerRegistry.getInstance().findInstanceContainers(id = material_id)
@ -667,18 +526,67 @@ class MachineManager(QObject):
@pyqtSlot(str) @pyqtSlot(str)
def setActiveQuality(self, quality_id): def setActiveQuality(self, quality_id):
containers = UM.Settings.ContainerRegistry.getInstance().findInstanceContainers(id = 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 return
old_quality = self._active_container_stack.findContainer({"type": "quality"}) quality_container = None
if old_quality and old_quality != containers[0]: quality_changes_container = self._empty_quality_changes_container
container_type = containers[0].getMetaDataEntry("type")
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("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_quality.nameChanged.disconnect(self._onQualityNameChanged)
old_changes = stack.findContainer(type = "quality_changes")
old_changes.nameChanged.disconnect(self._onQualityNameChanged)
quality_index = self._active_container_stack.getContainerIndex(old_quality) stack.replaceContainer(stack.getContainerIndex(old_quality), stack_quality)
stack.replaceContainer(stack.getContainerIndex(old_changes), stack_quality_changes)
self._active_container_stack.replaceContainer(quality_index, containers[0]) stack_quality.nameChanged.connect(self._onQualityNameChanged)
stack_quality_changes.nameChanged.connect(self._onQualityNameChanged)
containers[0].nameChanged.connect(self._onQualityNameChanged)
if self.hasUserSettings and Preferences.getInstance().getValue("cura/active_mode") == 1: 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) # Ask the user if the user profile should be cleared or not (discarding the current settings)
@ -691,8 +599,8 @@ class MachineManager(QObject):
Application.getInstance().messageBox(catalog.i18nc("@window:title", "Switched profiles"), catalog.i18nc("@label", "Do you want to transfer your changed settings to this profile?"), 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, 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) buttons = QMessageBox.Yes + QMessageBox.No, icon = QMessageBox.Question, callback = self._keepUserSettingsDialogCallback)
else:
Logger.log("w", "While trying to set the active quality, no quality was found to replace.") self.activeQualityChanged.emit()
def _keepUserSettingsDialogCallback(self, button): def _keepUserSettingsDialogCallback(self, button):
if button == QMessageBox.Yes: if button == QMessageBox.Yes:
@ -700,7 +608,11 @@ class MachineManager(QObject):
pass pass
elif button == QMessageBox.No: elif button == QMessageBox.No:
# No, discard the settings in the user profile # 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) @pyqtProperty(str, notify = activeVariantChanged)
def activeVariantName(self): def activeVariantName(self):

View file

@ -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
})

View file

@ -10,3 +10,4 @@ from .ExtrudersModel import ExtrudersModel
from .MachineManager import MachineManager from .MachineManager import MachineManager
from .MaterialSettingsVisibilityHandler import MaterialSettingsVisibilityHandler from .MaterialSettingsVisibilityHandler import MaterialSettingsVisibilityHandler
from .SettingOverrideDecorator import SettingOverrideDecorator from .SettingOverrideDecorator import SettingOverrideDecorator
from .QualitySettingsModel import QualitySettingsModel

View file

@ -122,7 +122,7 @@ Item
id: updateProfileAction; id: updateProfileAction;
enabled: Cura.MachineManager.isActiveStackValid && Cura.MachineManager.hasUserSettings && !Cura.MachineManager.isReadOnly(Cura.MachineManager.activeQualityId) 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"); text: catalog.i18nc("@action:inmenu menubar:profile","&Update profile with current settings");
onTriggered: Cura.MachineManager.updateQualityContainerFromUserContainer() onTriggered: Cura.ContainerManager.updateQualityChanges();
} }
Action Action
@ -130,7 +130,7 @@ Item
id: resetProfileAction; id: resetProfileAction;
enabled: Cura.MachineManager.hasUserSettings enabled: Cura.MachineManager.hasUserSettings
text: catalog.i18nc("@action:inmenu menubar:profile","&Discard current settings"); text: catalog.i18nc("@action:inmenu menubar:profile","&Discard current settings");
onTriggered: Cura.MachineManager.clearUserSettings(); onTriggered: Cura.ContainerManager.clearUserContainers();
} }
Action Action

View file

@ -150,7 +150,7 @@ UM.MainWindow
MenuSeparator { } 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) onObjectAdded: settingsMenu.insertItem(index, object)
onObjectRemoved: settingsMenu.removeItem(object) onObjectRemoved: settingsMenu.removeItem(object)
@ -459,7 +459,7 @@ UM.MainWindow
target: Cura.Actions.addProfile target: Cura.Actions.addProfile
onTriggered: onTriggered:
{ {
Cura.MachineManager.newQualityContainerFromQualityAndUser(); Cura.ContainerManager.createQualityChanges();
preferences.setPage(4); preferences.setPage(4);
preferences.show(); preferences.show();

View file

@ -7,7 +7,7 @@ import QtQuick.Controls 1.1
import UM 1.2 as UM import UM 1.2 as UM
import Cura 1.0 as Cura import Cura 1.0 as Cura
Menu Menu
{ {
id: menu id: menu
@ -15,14 +15,14 @@ import Cura 1.0 as Cura
{ {
model: UM.InstanceContainersModel model: UM.InstanceContainersModel
{ {
filter: menu.getFilter({ "read_only": true }); filter: menu.getFilter({ "type": "quality" });
} }
MenuItem MenuItem
{ {
text: model.name text: model.name
checkable: true checkable: true
checked: Cura.MachineManager.activeQualityId == model.id checked: Cura.MachineManager.activeQualityChangesId == "empty_quality_changes" && Cura.MachineManager.activeQualityType == model.metadata.quality_type
exclusiveGroup: group exclusiveGroup: group
onTriggered: Cura.MachineManager.setActiveQuality(model.id) onTriggered: Cura.MachineManager.setActiveQuality(model.id)
} }
@ -38,7 +38,7 @@ import Cura 1.0 as Cura
id: customProfileInstantiator id: customProfileInstantiator
model: UM.InstanceContainersModel 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 onModelReset: customSeparator.visible = rowCount() > 0
} }
@ -76,7 +76,6 @@ import Cura 1.0 as Cura
function getFilter(initial_conditions) function getFilter(initial_conditions)
{ {
var result = initial_conditions; var result = initial_conditions;
result.type = "quality"
if(Cura.MachineManager.filterQualityByMachine) if(Cura.MachineManager.filterQualityByMachine)
{ {

View file

@ -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
}
}
}

View file

@ -18,13 +18,13 @@ UM.ManagementPage
{ {
filter: filter:
{ {
var result = { "type": "quality" }; var result = { "type": "quality*", "extruder": null };
if(Cura.MachineManager.filterQualityByMachine) if(Cura.MachineManager.filterQualityByMachine)
{ {
result.definition = Cura.MachineManager.activeDefinitionId; result.definition = Cura.MachineManager.activeDefinitionId;
if(Cura.MachineManager.hasMaterials) if(Cura.MachineManager.hasMaterials)
{ {
result.material = Cura.MachineManager.activeMaterialId; result.material = Cura.MachineManager.allActiveMaterialIds[Cura.MachineManager.activeMachineId];
} }
} }
else else
@ -76,9 +76,9 @@ UM.ManagementPage
{ {
var selectedContainer; var selectedContainer;
if (base.currentItem.id == Cura.MachineManager.activeQualityId) { if (base.currentItem.id == Cura.MachineManager.activeQualityId) {
selectedContainer = Cura.MachineManager.newQualityContainerFromQualityAndUser(); selectedContainer = Cura.ContainerManager.createQualityChanges();
} else { } else {
selectedContainer = Cura.MachineManager.duplicateContainer(base.currentItem.id); selectedContainer = Cura.ContainerManager.duplicateQualityOrQualityChanges(base.currentItem.name);
} }
base.selectContainer(selectedContainer); base.selectContainer(selectedContainer);
@ -106,13 +106,15 @@ UM.ManagementPage
text: catalog.i18nc("@action:button", "Import"); text: catalog.i18nc("@action:button", "Import");
iconName: "document-import"; iconName: "document-import";
onClicked: importDialog.open(); onClicked: importDialog.open();
enabled: false
}, },
Button Button
{ {
text: catalog.i18nc("@action:button", "Export") text: catalog.i18nc("@action:button", "Export")
iconName: "document-export" iconName: "document-export"
onClicked: exportDialog.open() 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"); return catalog.i18nc("@action:button", "Update profile with current settings");
} }
enabled: Cura.MachineManager.hasUserSettings && !Cura.MachineManager.isReadOnly(Cura.MachineManager.activeQualityId) enabled: Cura.MachineManager.hasUserSettings && !Cura.MachineManager.isReadOnly(Cura.MachineManager.activeQualityId)
onClicked: Cura.MachineManager.updateQualityContainerFromUserContainer() onClicked: Cura.ContainerManager.updateQualityChanges()
} }
Button Button
{ {
text: catalog.i18nc("@action:button", "Discard current settings"); text: catalog.i18nc("@action:button", "Discard current settings");
enabled: Cura.MachineManager.hasUserSettings enabled: Cura.MachineManager.hasUserSettings
onClicked: Cura.MachineManager.clearUserSettings(); onClicked: Cura.ContainerManager.clearUserContainers();
} }
} }
@ -173,7 +175,7 @@ UM.ManagementPage
Label { Label {
id: defaultsMessage 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.") text: catalog.i18nc("@action:label", "This profile has no settings and uses the defaults specified by the printer.")
wrapMode: Text.WordWrap wrapMode: Text.WordWrap
width: parent.width width: parent.width
@ -187,71 +189,31 @@ UM.ManagementPage
} }
} }
ScrollView { TabView
id: scrollView {
anchors.left: parent.left anchors.left: parent.left
anchors.top: profileNotices.visible ? profileNotices.bottom : profileNotices.anchors.top anchors.top: profileNotices.visible ? profileNotices.bottom : profileNotices.anchors.top
anchors.topMargin: UM.Theme.getSize("default_margin").height anchors.topMargin: UM.Theme.getSize("default_margin").height
anchors.right: parent.right anchors.right: parent.right
anchors.bottom: parent.bottom anchors.bottom: parent.bottom
ListView { ProfileTab
model: Cura.ContainerSettingsModel
{ {
containers: title: catalog.i18nc("@title:tab", "Global Settings");
quality: base.currentItem != null ? base.currentItem.id : "";
material: Cura.MachineManager.allActiveMaterialIds.global
}
Repeater
{ {
if (!currentItem) { model: Cura.ExtrudersModel { }
return []
} else if (currentItem.id == Cura.MachineManager.activeQualityId) { ProfileTab
return [base.currentItem.id, Cura.MachineManager.activeUserProfileId] {
} else { title: model.name;
return [base.currentItem.id] extruderId: model.id;
} quality: base.currentItem != null ? base.currentItem.id : null;
} material: Cura.MachineManager.allActiveMaterialIds[model.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
} }
} }
} }
@ -265,17 +227,25 @@ UM.ManagementPage
{ {
id: confirmDialog id: confirmDialog
object: base.currentItem != null ? base.currentItem.name : "" 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 UM.RenameDialog
{ {
id: renameDialog; id: renameDialog;
object: base.currentItem != null ? base.currentItem.name : "" object: base.currentItem != null ? base.currentItem.name : ""
property bool removeWhenRejected: false property bool removeWhenRejected: false
onAccepted: Cura.MachineManager.renameQualityContainer(base.currentItem.id, newName) onAccepted: Cura.ContainerManager.renameQualityChanges(base.currentItem.name, newName)
onRejected: { onRejected: {
if(removeWhenRejected) { if(removeWhenRejected) {
Cura.MachineManager.removeQualityContainer(base.currentItem.id) Cura.ContainerManager.removeQualityChanges(base.currentItem.name)
} }
} }
} }

View file

@ -27,7 +27,6 @@ Item {
// Create properties to put property provider stuff in (bindings break in qt 5.5.1 otherwise) // Create properties to put property provider stuff in (bindings break in qt 5.5.1 otherwise)
property var state: propertyProvider.properties.state property var state: propertyProvider.properties.state
property var settablePerExtruder: propertyProvider.properties.settable_per_extruder
property var stackLevels: propertyProvider.stackLevels property var stackLevels: propertyProvider.stackLevels
property var stackLevel: stackLevels[0] property var stackLevel: stackLevels[0]
@ -138,7 +137,7 @@ Item {
{ {
id: linkedSettingIcon; 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; height: parent.height;
width: height; width: height;

View file

@ -94,31 +94,37 @@ ScrollView
{ {
target: provider target: provider
property: "containerStackId" property: "containerStackId"
when: model.settable_per_extruder || model.settable_per_mesh || (inheritStackProvider.properties.global_inherits_stack != null && inheritStackProvider.properties.global_inherits_stack >= 0);
value: 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) //Not settable per extruder, so we must pick global.
return Cura.MachineManager.activeMachineId;
}
if(inheritStackProvider.properties.global_inherits_stack != null && inheritStackProvider.properties.global_inherits_stack >= 0)
{ {
return ExtruderManager.activeExtruderStackId //We have global_inherits_stack, so pick that stack.
return ExtruderManager.extruderIds[String(inheritStackProvider.properties.global_inherits_stack)];
} }
else if(ExtruderManager.activeExtruderStackId)
{ {
return Cura.MachineManager.activeMachineId //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 ExtruderManager.extruderIds[String(inheritStackProvider.properties.global_inherits_stack)] return Cura.MachineManager.activeMachineId;
} }
} }
// Specialty provider that only watches global_inherits (we cant filter on what property changed we get events // 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 UM.SettingPropertyProvider
{ {
id: inheritStackProvider id: inheritStackProvider
containerStackId: Cura.MachineManager.activeMachineId containerStackId: Cura.MachineManager.activeMachineId
key: model.key key: model.key
watchedProperties: [ "global_inherits_stack"] watchedProperties: [ "global_inherits_stack" ]
} }
UM.SettingPropertyProvider UM.SettingPropertyProvider
@ -127,7 +133,7 @@ ScrollView
containerStackId: Cura.MachineManager.activeMachineId containerStackId: Cura.MachineManager.activeMachineId
key: model.key ? model.key : "" key: model.key ? model.key : ""
watchedProperties: [ "value", "enabled", "state", "validationState", "settable_per_extruder" ] watchedProperties: [ "value", "enabled", "state", "validationState" ]
storeIndex: 0 storeIndex: 0
} }

View file

@ -5,6 +5,7 @@ definition = fdmprinter
[metadata] [metadata]
type = quality type = quality
quality_type = high
weight = -3 weight = -3
[values] [values]

View file

@ -5,6 +5,7 @@ definition = fdmprinter
[metadata] [metadata]
type = quality type = quality
quality_type = low
weight = -1 weight = -1
[values] [values]

View file

@ -5,6 +5,7 @@ definition = fdmprinter
[metadata] [metadata]
type = quality type = quality
quality_type = normal
weight = -2 weight = -2
[values] [values]

View file

@ -7,6 +7,7 @@ definition = ultimaker2_extended_plus
type = quality type = quality
material = generic_abs_ultimaker2_extended_plus_0.25_mm material = generic_abs_ultimaker2_extended_plus_0.25_mm
weight = -2 weight = -2
quality_type = high
[values] [values]
layer_height = 0.06 layer_height = 0.06

View file

@ -7,6 +7,7 @@ definition = ultimaker2_extended_plus
type = quality type = quality
material = generic_abs_ultimaker2_extended_plus_0.4_mm material = generic_abs_ultimaker2_extended_plus_0.4_mm
weight = -1 weight = -1
quality_type = fast
[values] [values]
layer_height = 0.15 layer_height = 0.15

View file

@ -7,6 +7,7 @@ definition = ultimaker2_extended_plus
type = quality type = quality
material = generic_abs_ultimaker2_extended_plus_0.4_mm material = generic_abs_ultimaker2_extended_plus_0.4_mm
weight = -3 weight = -3
quality_type = high
[values] [values]
layer_height = 0.06 layer_height = 0.06

View file

@ -7,6 +7,7 @@ definition = ultimaker2_extended_plus
type = quality type = quality
material = generic_abs_ultimaker2_extended_plus_0.4_mm material = generic_abs_ultimaker2_extended_plus_0.4_mm
weight = -2 weight = -2
quality_type = normal
[values] [values]
layer_height = 0.1 layer_height = 0.1

View file

@ -7,6 +7,7 @@ definition = ultimaker2_extended_plus
type = quality type = quality
material = generic_abs_ultimaker2_extended_plus_0.6_mm material = generic_abs_ultimaker2_extended_plus_0.6_mm
weight = -2 weight = -2
quality_type = normal
[values] [values]
layer_height = 0.15 layer_height = 0.15

View file

@ -7,6 +7,7 @@ definition = ultimaker2_extended_plus
type = quality type = quality
material = generic_abs_ultimaker2_extended_plus_0.8_mm material = generic_abs_ultimaker2_extended_plus_0.8_mm
weight = -2 weight = -2
quality_type = fast
[values] [values]
layer_height = 0.2 layer_height = 0.2

View file

@ -7,6 +7,7 @@ definition = ultimaker2_extended_plus
type = quality type = quality
material = generic_cpe_ultimaker2_extended_plus_0.25_mm material = generic_cpe_ultimaker2_extended_plus_0.25_mm
weight = -2 weight = -2
quality_type = high
[values] [values]
layer_height = 0.06 layer_height = 0.06

View file

@ -7,6 +7,7 @@ definition = ultimaker2_extended_plus
type = quality type = quality
material = generic_cpe_ultimaker2_extended_plus_0.4_mm material = generic_cpe_ultimaker2_extended_plus_0.4_mm
weight = -1 weight = -1
quality_type = fast
[values] [values]
layer_height = 0.15 layer_height = 0.15

View file

@ -7,6 +7,7 @@ definition = ultimaker2_extended_plus
type = quality type = quality
material = generic_cpe_ultimaker2_extended_plus_0.4_mm material = generic_cpe_ultimaker2_extended_plus_0.4_mm
weight = -3 weight = -3
quality_type = high
[values] [values]
layer_height = 0.06 layer_height = 0.06

View file

@ -7,6 +7,7 @@ definition = ultimaker2_extended_plus
type = quality type = quality
material = generic_cpe_ultimaker2_extended_plus_0.4_mm material = generic_cpe_ultimaker2_extended_plus_0.4_mm
weight = -2 weight = -2
quality_type = normal
[values] [values]
layer_height = 0.1 layer_height = 0.1

View file

@ -7,6 +7,7 @@ definition = ultimaker2_extended_plus
type = quality type = quality
material = generic_cpe_ultimaker2_extended_plus_0.6_mm material = generic_cpe_ultimaker2_extended_plus_0.6_mm
weight = -2 weight = -2
quality_type = normal
[values] [values]
layer_height = 0.15 layer_height = 0.15

View file

@ -7,6 +7,7 @@ definition = ultimaker2_extended_plus
type = quality type = quality
material = generic_cpe_ultimaker2_extended_plus_0.8_mm material = generic_cpe_ultimaker2_extended_plus_0.8_mm
weight = -2 weight = -2
quality_type = fast
[values] [values]
layer_height = 0.2 layer_height = 0.2

View file

@ -7,6 +7,7 @@ definition = ultimaker2_extended_plus
type = quality type = quality
material = generic_pla_ultimaker2_extended_plus_0.25_mm material = generic_pla_ultimaker2_extended_plus_0.25_mm
weight = -2 weight = -2
quality_type = high
[values] [values]
layer_height = 0.06 layer_height = 0.06

View file

@ -7,6 +7,7 @@ definition = ultimaker2_extended_plus
type = quality type = quality
material = generic_pla_ultimaker2_extended_plus_0.4_mm material = generic_pla_ultimaker2_extended_plus_0.4_mm
weight = -1 weight = -1
quality_type = fast
[values] [values]
layer_height = 0.15 layer_height = 0.15

View file

@ -7,6 +7,7 @@ definition = ultimaker2_extended_plus
type = quality type = quality
material = generic_pla_ultimaker2_extended_plus_0.4_mm material = generic_pla_ultimaker2_extended_plus_0.4_mm
weight = -3 weight = -3
quality_type = high
[values] [values]
layer_height = 0.06 layer_height = 0.06

View file

@ -7,6 +7,7 @@ definition = ultimaker2_extended_plus
type = quality type = quality
material = generic_pla_ultimaker2_extended_plus_0.4_mm material = generic_pla_ultimaker2_extended_plus_0.4_mm
weight = -2 weight = -2
quality_type = normal
[values] [values]
layer_height = 0.1 layer_height = 0.1

View file

@ -7,6 +7,7 @@ definition = ultimaker2_extended_plus
material = generic_pla_ultimaker2_extended_plus_0.6_mm material = generic_pla_ultimaker2_extended_plus_0.6_mm
type = quality type = quality
weight = -2 weight = -2
quality_type = normal
[values] [values]
layer_height = 0.15 layer_height = 0.15

View file

@ -7,6 +7,7 @@ definition = ultimaker2_extended_plus
material = generic_pla_ultimaker2_extended_plus_0.8_mm material = generic_pla_ultimaker2_extended_plus_0.8_mm
type = quality type = quality
weight = -2 weight = -2
quality_type = fast
[values] [values]
layer_height = 0.2 layer_height = 0.2

View file

@ -7,6 +7,7 @@ definition = ultimaker2_plus
type = quality type = quality
material = generic_pla_ultimaker2_plus_0.25_mm material = generic_pla_ultimaker2_plus_0.25_mm
weight = -2 weight = -2
quality_type = high
[values] [values]
layer_height = 0.06 layer_height = 0.06

View file

@ -7,6 +7,7 @@ definition = ultimaker2_plus
type = quality type = quality
material = generic_pla_ultimaker2_plus_0.4_mm material = generic_pla_ultimaker2_plus_0.4_mm
weight = -1 weight = -1
quality_type = fast
[values] [values]
layer_height = 0.15 layer_height = 0.15

View file

@ -7,6 +7,7 @@ definition = ultimaker2_plus
type = quality type = quality
material = generic_pla_ultimaker2_plus_0.4_mm material = generic_pla_ultimaker2_plus_0.4_mm
weight = -3 weight = -3
quality_type = high
[values] [values]
layer_height = 0.06 layer_height = 0.06

View file

@ -7,6 +7,7 @@ definition = ultimaker2_plus
type = quality type = quality
material = generic_pla_ultimaker2_plus_0.4_mm material = generic_pla_ultimaker2_plus_0.4_mm
weight = -2 weight = -2
quality_type = normal
[values] [values]
layer_height = 0.1 layer_height = 0.1

View file

@ -7,6 +7,7 @@ definition = ultimaker2_plus
material = generic_pla_ultimaker2_plus_0.6_mm material = generic_pla_ultimaker2_plus_0.6_mm
type = quality type = quality
weight = -2 weight = -2
quality_type = normal
[values] [values]
layer_height = 0.15 layer_height = 0.15

View file

@ -7,6 +7,7 @@ definition = ultimaker2_plus
material = generic_pla_ultimaker2_plus_0.8_mm material = generic_pla_ultimaker2_plus_0.8_mm
type = quality type = quality
weight = -2 weight = -2
quality_type = fast
[values] [values]
layer_height = 0.2 layer_height = 0.2

View file

@ -7,6 +7,7 @@ definition = ultimaker2_plus
type = quality type = quality
material = generic_abs_ultimaker2_plus_0.25_mm material = generic_abs_ultimaker2_plus_0.25_mm
weight = -2 weight = -2
quality_type = high
[values] [values]
layer_height = 0.06 layer_height = 0.06

View file

@ -7,6 +7,7 @@ definition = ultimaker2_plus
type = quality type = quality
material = generic_abs_ultimaker2_plus_0.4_mm material = generic_abs_ultimaker2_plus_0.4_mm
weight = -1 weight = -1
quality_type = fast
[values] [values]
layer_height = 0.15 layer_height = 0.15

View file

@ -7,6 +7,7 @@ definition = ultimaker2_plus
type = quality type = quality
material = generic_abs_ultimaker2_plus_0.4_mm material = generic_abs_ultimaker2_plus_0.4_mm
weight = -3 weight = -3
quality_type = high
[values] [values]
layer_height = 0.06 layer_height = 0.06

View file

@ -7,6 +7,7 @@ definition = ultimaker2_plus
type = quality type = quality
material = generic_abs_ultimaker2_plus_0.4_mm material = generic_abs_ultimaker2_plus_0.4_mm
weight = -2 weight = -2
quality_type = normal
[values] [values]
layer_height = 0.1 layer_height = 0.1

View file

@ -7,6 +7,7 @@ definition = ultimaker2_plus
type = quality type = quality
material = generic_abs_ultimaker2_plus_0.6_mm material = generic_abs_ultimaker2_plus_0.6_mm
weight = -2 weight = -2
quality_type = normal
[values] [values]
layer_height = 0.15 layer_height = 0.15

View file

@ -7,6 +7,7 @@ definition = ultimaker2_plus
type = quality type = quality
material = generic_abs_ultimaker2_plus_0.8_mm material = generic_abs_ultimaker2_plus_0.8_mm
weight = -2 weight = -2
quality_type = fast
[values] [values]
layer_height = 0.2 layer_height = 0.2

View file

@ -7,6 +7,7 @@ definition = ultimaker2_plus
type = quality type = quality
material = generic_cpe_ultimaker2_plus_0.25_mm material = generic_cpe_ultimaker2_plus_0.25_mm
weight = -2 weight = -2
quality_type = high
[values] [values]
layer_height = 0.06 layer_height = 0.06

View file

@ -7,6 +7,7 @@ definition = ultimaker2_plus
type = quality type = quality
material = generic_cpe_ultimaker2_plus_0.4_mm material = generic_cpe_ultimaker2_plus_0.4_mm
weight = -1 weight = -1
quality_type = fast
[values] [values]
layer_height = 0.15 layer_height = 0.15

View file

@ -7,6 +7,7 @@ definition = ultimaker2_plus
type = quality type = quality
material = generic_cpe_ultimaker2_plus_0.4_mm material = generic_cpe_ultimaker2_plus_0.4_mm
weight = -3 weight = -3
quality_type = high
[values] [values]
layer_height = 0.06 layer_height = 0.06

View file

@ -7,6 +7,7 @@ definition = ultimaker2_plus
type = quality type = quality
material = generic_cpe_ultimaker2_plus_0.4_mm material = generic_cpe_ultimaker2_plus_0.4_mm
weight = -2 weight = -2
quality_type = normal
[values] [values]
layer_height = 0.1 layer_height = 0.1

View file

@ -7,6 +7,7 @@ definition = ultimaker2_plus
type = quality type = quality
material = generic_cpe_ultimaker2_plus_0.6_mm material = generic_cpe_ultimaker2_plus_0.6_mm
weight = -2 weight = -2
quality_type = normal
[values] [values]
layer_height = 0.15 layer_height = 0.15

View file

@ -7,6 +7,7 @@ definition = ultimaker2_plus
type = quality type = quality
material = generic_cpe_ultimaker2_plus_0.8_mm material = generic_cpe_ultimaker2_plus_0.8_mm
weight = -2 weight = -2
quality_type = fast
[values] [values]
layer_height = 0.2 layer_height = 0.2