mirror of
https://github.com/Ultimaker/Cura.git
synced 2025-07-07 23:17:32 -06:00
Merge branch 'feature_quality_changes'
This commit is contained in:
commit
bb90c593b9
52 changed files with 747 additions and 346 deletions
|
@ -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)
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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()
|
||||
|
|
|
@ -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,18 +526,67 @@ 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]:
|
||||
quality_container = None
|
||||
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_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])
|
||||
|
||||
containers[0].nameChanged.connect(self._onQualityNameChanged)
|
||||
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)
|
||||
|
@ -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?"),
|
||||
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)
|
||||
else:
|
||||
Logger.log("w", "While trying to set the active quality, no quality was found to replace.")
|
||||
|
||||
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):
|
||||
|
|
156
cura/Settings/QualitySettingsModel.py
Normal file
156
cura/Settings/QualitySettingsModel.py
Normal 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
|
||||
})
|
|
@ -10,3 +10,4 @@ from .ExtrudersModel import ExtrudersModel
|
|||
from .MachineManager import MachineManager
|
||||
from .MaterialSettingsVisibilityHandler import MaterialSettingsVisibilityHandler
|
||||
from .SettingOverrideDecorator import SettingOverrideDecorator
|
||||
from .QualitySettingsModel import QualitySettingsModel
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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();
|
||||
|
||||
|
|
|
@ -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)
|
||||
{
|
||||
|
|
38
resources/qml/Preferences/ProfileTab.qml
Normal file
38
resources/qml/Preferences/ProfileTab.qml
Normal 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
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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
|
||||
{
|
||||
containers:
|
||||
title: catalog.i18nc("@title:tab", "Global Settings");
|
||||
quality: base.currentItem != null ? base.currentItem.id : "";
|
||||
material: Cura.MachineManager.allActiveMaterialIds.global
|
||||
}
|
||||
|
||||
Repeater
|
||||
{
|
||||
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
|
||||
model: Cura.ExtrudersModel { }
|
||||
|
||||
ProfileTab
|
||||
{
|
||||
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)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -94,25 +94,31 @@ 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)
|
||||
{
|
||||
//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)
|
||||
{
|
||||
//We have global_inherits_stack, so pick that stack.
|
||||
return ExtruderManager.extruderIds[String(inheritStackProvider.properties.global_inherits_stack)];
|
||||
}
|
||||
if(ExtruderManager.activeExtruderStackId)
|
||||
{
|
||||
return ExtruderManager.activeExtruderStackId
|
||||
//We're on an extruder tab. Pick the current extruder.
|
||||
return ExtruderManager.activeExtruderStackId;
|
||||
}
|
||||
else
|
||||
{
|
||||
return Cura.MachineManager.activeMachineId
|
||||
}
|
||||
}
|
||||
return ExtruderManager.extruderIds[String(inheritStackProvider.properties.global_inherits_stack)]
|
||||
//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
|
||||
|
@ -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
|
||||
}
|
||||
|
||||
|
|
|
@ -5,6 +5,7 @@ definition = fdmprinter
|
|||
|
||||
[metadata]
|
||||
type = quality
|
||||
quality_type = high
|
||||
weight = -3
|
||||
|
||||
[values]
|
||||
|
|
|
@ -5,6 +5,7 @@ definition = fdmprinter
|
|||
|
||||
[metadata]
|
||||
type = quality
|
||||
quality_type = low
|
||||
weight = -1
|
||||
|
||||
[values]
|
||||
|
|
|
@ -5,6 +5,7 @@ definition = fdmprinter
|
|||
|
||||
[metadata]
|
||||
type = quality
|
||||
quality_type = normal
|
||||
weight = -2
|
||||
|
||||
[values]
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue