Merge branch 'settings_rework' of https://github.com/Ultimaker/Cura into settings_rework

This commit is contained in:
Jaime van Kessel 2016-05-25 11:50:22 +02:00
commit 5ba3f3ebad
9 changed files with 189 additions and 71 deletions

View File

@ -8,7 +8,10 @@ import UM.Settings
class MachineManagerModel(QObject): class MachineManagerModel(QObject):
def __init__(self, parent = None): def __init__(self, parent = None):
super().__init__(parent) super().__init__(parent)
self._global_container_stack = None
Application.getInstance().globalContainerStackChanged.connect(self._onGlobalContainerChanged) Application.getInstance().globalContainerStackChanged.connect(self._onGlobalContainerChanged)
self._onGlobalContainerChanged()
## When the global container is changed, active material probably needs to be updated. ## When the global container is changed, active material probably needs to be updated.
self.globalContainerChanged.connect(self.activeMaterialChanged) self.globalContainerChanged.connect(self.activeMaterialChanged)
@ -31,10 +34,16 @@ class MachineManagerModel(QObject):
activeQualityChanged = pyqtSignal() activeQualityChanged = pyqtSignal()
def _onGlobalContainerChanged(self): def _onGlobalContainerChanged(self):
Preferences.getInstance().setValue("cura/active_machine", Application.getInstance().getGlobalContainerStack().getId()) if self._global_container_stack:
Application.getInstance().getGlobalContainerStack().containersChanged.connect(self._onInstanceContainersChanged) self._global_container_stack.containersChanged.disconnect(self._onInstanceContainersChanged)
self._global_container_stack = Application.getInstance().getGlobalContainerStack()
self.globalContainerChanged.emit() self.globalContainerChanged.emit()
if self._global_container_stack:
Preferences.getInstance().setValue("cura/active_machine", self._global_container_stack.getId())
self._global_container_stack.containersChanged.connect(self._onInstanceContainersChanged)
def _onInstanceContainersChanged(self, container): def _onInstanceContainersChanged(self, container):
container_type = container.getMetaDataEntry("type") container_type = container.getMetaDataEntry("type")
if container_type == "material": if container_type == "material":
@ -54,34 +63,52 @@ class MachineManagerModel(QObject):
def addMachine(self,name, definition_id): def addMachine(self,name, definition_id):
definitions = UM.Settings.ContainerRegistry.getInstance().findDefinitionContainers(id=definition_id) definitions = UM.Settings.ContainerRegistry.getInstance().findDefinitionContainers(id=definition_id)
if definitions: if definitions:
definition = definitions[0]
new_global_stack = UM.Settings.ContainerStack(name) new_global_stack = UM.Settings.ContainerStack(name)
new_global_stack.addMetaDataEntry("type", "machine") new_global_stack.addMetaDataEntry("type", "machine")
UM.Settings.ContainerRegistry.getInstance().addContainer(new_global_stack) UM.Settings.ContainerRegistry.getInstance().addContainer(new_global_stack)
empty_container = UM.Settings.ContainerRegistry.getInstance().getEmptyInstanceContainer()
variants = UM.Settings.ContainerRegistry.getInstance().findInstanceContainers(type = "variant", definition = definition.id)
if variants:
new_global_stack.addMetaDataEntry("has_variants", True)
preferred_variant_id = definitions[0].getMetaDataEntry("preferred_variant")
variant_instance_container = empty_container
if preferred_variant_id:
preferred_variant_id = preferred_variant_id.lower()
container = UM.Settings.ContainerRegistry.getInstance().findInstanceContainers(id = preferred_variant_id)
if container:
variant_instance_container = container[0]
if variants and variant_instance_container == empty_container:
variant_instance_container = variants[0]
materials = UM.Settings.ContainerRegistry.getInstance().findInstanceContainers(type = "material", definition = definition.id)
if materials:
new_global_stack.addMetaDataEntry("has_materials", True)
preferred_material_id = definitions[0].getMetaDataEntry("preferred_material") preferred_material_id = definitions[0].getMetaDataEntry("preferred_material")
material_instance_container = None material_instance_container = empty_container
if preferred_material_id: if preferred_material_id:
preferred_material_id = preferred_material_id.lower() preferred_material_id = preferred_material_id.lower()
container = UM.Settings.ContainerRegistry.getInstance().findInstanceContainers(id = preferred_material_id) container = UM.Settings.ContainerRegistry.getInstance().findInstanceContainers(id = preferred_material_id)
if container: if container:
material_instance_container = container[0] material_instance_container = container[0]
if materials and material_instance_container == empty_container:
material_instance_container = materials[0]
preferred_quality_id = definitions[0].getMetaDataEntry("preferred_quality") preferred_quality_id = definitions[0].getMetaDataEntry("preferred_quality")
quality_instance_container = None quality_instance_container = empty_container
if preferred_quality_id: if preferred_quality_id:
preferred_quality_id = preferred_quality_id.lower() preferred_quality_id = preferred_quality_id.lower()
container = UM.Settings.ContainerRegistry.getInstance().findInstanceContainers(id = preferred_quality_id) container = UM.Settings.ContainerRegistry.getInstance().findInstanceContainers(id = preferred_quality_id)
if container: if container:
quality_instance_container = container[0] quality_instance_container = container[0]
## DEBUG CODE
variant_instance_container = UM.Settings.InstanceContainer("test_variant")
variant_instance_container.addMetaDataEntry("type", "variant")
variant_instance_container.setDefinition(definitions[0])
UM.Settings.ContainerRegistry.getInstance().addContainer(variant_instance_container)
current_settings_instance_container = UM.Settings.InstanceContainer(name + "_current_settings") current_settings_instance_container = UM.Settings.InstanceContainer(name + "_current_settings")
current_settings_instance_container.addMetaDataEntry("machine", name) current_settings_instance_container.addMetaDataEntry("machine", name)
current_settings_instance_container.addMetaDataEntry("type", "user") current_settings_instance_container.addMetaDataEntry("type", "user")
@ -90,9 +117,10 @@ class MachineManagerModel(QObject):
# If a definition is found, its a list. Should only have one item. # If a definition is found, its a list. Should only have one item.
new_global_stack.addContainer(definitions[0]) new_global_stack.addContainer(definitions[0])
if variant_instance_container:
new_global_stack.addContainer(variant_instance_container)
if material_instance_container: if material_instance_container:
new_global_stack.addContainer(material_instance_container) new_global_stack.addContainer(material_instance_container)
new_global_stack.addContainer(variant_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(current_settings_instance_container) new_global_stack.addContainer(current_settings_instance_container)
@ -101,78 +129,111 @@ class MachineManagerModel(QObject):
@pyqtProperty(str, notify = globalContainerChanged) @pyqtProperty(str, notify = globalContainerChanged)
def activeMachineName(self): def activeMachineName(self):
return Application.getInstance().getGlobalContainerStack().getName() if self._global_container_stack:
return self._global_container_stack.getName()
return ""
@pyqtProperty(str, notify = globalContainerChanged) @pyqtProperty(str, notify = globalContainerChanged)
def activeMachineId(self): def activeMachineId(self):
return Application.getInstance().getGlobalContainerStack().getId() if self._global_container_stack:
return self._global_container_stack.getId()
return ""
@pyqtProperty(str, notify = activeMaterialChanged) @pyqtProperty(str, notify = activeMaterialChanged)
def activeMaterialName(self): def activeMaterialName(self):
material = Application.getInstance().getGlobalContainerStack().findContainer({"type":"material"}) if self._global_container_stack:
if material: material = self._global_container_stack.findContainer({"type":"material"})
return material.getName() if material:
return material.getName()
return ""
@pyqtProperty(str, notify=activeMaterialChanged) @pyqtProperty(str, notify=activeMaterialChanged)
def activeMaterialId(self): def activeMaterialId(self):
material = Application.getInstance().getGlobalContainerStack().findContainer({"type": "material"}) if self._global_container_stack:
if material: material = self._global_container_stack.findContainer({"type": "material"})
return material.getId() if material:
return material.getId()
return ""
@pyqtProperty(str, notify=activeQualityChanged) @pyqtProperty(str, notify=activeQualityChanged)
def activeQualityName(self): def activeQualityName(self):
quality = Application.getInstance().getGlobalContainerStack().findContainer({"type": "quality"}) if self._global_container_stack:
if quality: quality = self._global_container_stack.findContainer({"type": "quality"})
return quality.getName() if quality:
return quality.getName()
return ""
@pyqtProperty(str, notify=activeQualityChanged) @pyqtProperty(str, notify=activeQualityChanged)
def activeQualityId(self): def activeQualityId(self):
quality = Application.getInstance().getGlobalContainerStack().findContainer({"type": "quality"}) if self._global_container_stack:
if quality: quality = self._global_container_stack.findContainer({"type": "quality"})
return quality.getId() if quality:
return quality.getId()
return ""
@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)
old_material = Application.getInstance().getGlobalContainerStack().findContainer({"type":"material"}) if not containers or not self._global_container_stack:
return
old_material = self._global_container_stack.findContainer({"type":"material"})
if old_material: if old_material:
material_index = Application.getInstance().getGlobalContainerStack().getContainerIndex(old_material) material_index = self._global_container_stack.getContainerIndex(old_material)
Application.getInstance().getGlobalContainerStack().replaceContainer(material_index, containers[0]) self._global_container_stack.replaceContainer(material_index, containers[0])
@pyqtSlot(str) @pyqtSlot(str)
def setActiveVariant(self, variant_id): def setActiveVariant(self, variant_id):
containers = UM.Settings.ContainerRegistry.getInstance().findInstanceContainers(id=variant_id) containers = UM.Settings.ContainerRegistry.getInstance().findInstanceContainers(id=variant_id)
old_variant = Application.getInstance().getGlobalContainerStack().findContainer({"type": "variant"}) if not containers or not self._global_container_stack:
return
old_variant = self._global_container_stack.findContainer({"type": "variant"})
if old_variant: if old_variant:
variant_index = Application.getInstance().getGlobalContainerStack().getContainerIndex(old_variant) variant_index = self._global_container_stack.getContainerIndex(old_variant)
Application.getInstance().getGlobalContainerStack().replaceContainer(variant_index, containers[0]) self._global_container_stack.replaceContainer(variant_index, containers[0])
@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)
old_quality = Application.getInstance().getGlobalContainerStack().findContainer({"type": "quality"}) if not containers or not self._global_container_stack:
return
old_quality = self._global_container_stack.findContainer({"type": "quality"})
if old_quality: if old_quality:
quality_index = Application.getInstance().getGlobalContainerStack().getContainerIndex(old_quality) quality_index = self._global_container_stack.getContainerIndex(old_quality)
Application.getInstance().getGlobalContainerStack().replaceContainer(quality_index, containers[0]) self._global_container_stack.replaceContainer(quality_index, containers[0])
@pyqtProperty(str, notify = activeVariantChanged) @pyqtProperty(str, notify = activeVariantChanged)
def activeVariantName(self): def activeVariantName(self):
variant = Application.getInstance().getGlobalContainerStack().findContainer({"type": "variant"}) if self._global_container_stack:
if variant: variant = self._global_container_stack.findContainer({"type": "variant"})
return variant.getName() if variant:
return variant.getName()
return ""
@pyqtProperty(str, notify = activeVariantChanged) @pyqtProperty(str, notify = activeVariantChanged)
def activeVariantId(self): def activeVariantId(self):
variant = Application.getInstance().getGlobalContainerStack().findContainer({"type": "variant"}) if self._global_container_stack:
if variant: variant = self._global_container_stack.findContainer({"type": "variant"})
return variant.getId() if variant:
return variant.getId()
return ""
@pyqtProperty(str, notify = globalContainerChanged) @pyqtProperty(str, notify = globalContainerChanged)
def activeDefinitionId(self): def activeDefinitionId(self):
definition = Application.getInstance().getGlobalContainerStack().getBottom() if self._global_container_stack:
if definition: definition = self._global_container_stack.getBottom()
return definition.id if definition:
return None return definition.id
return ""
@pyqtSlot(str, str) @pyqtSlot(str, str)
def renameMachine(self, machine_id, new_name): def renameMachine(self, machine_id, new_name):
@ -184,17 +245,19 @@ class MachineManagerModel(QObject):
def removeMachine(self, machine_id): def removeMachine(self, machine_id):
UM.Settings.ContainerRegistry.getInstance().removeContainer(machine_id) UM.Settings.ContainerRegistry.getInstance().removeContainer(machine_id)
@pyqtProperty(bool) @pyqtProperty(bool, notify = globalContainerChanged)
def hasMaterials(self): def hasMaterials(self):
# Todo: Still hardcoded. if self._global_container_stack:
# We should implement this properly when it's clear how a machine notifies us if it can handle materials return self._global_container_stack.getMetaDataEntry("has_materials", False)
return True
@pyqtProperty(bool) return False
@pyqtProperty(bool, notify = globalContainerChanged)
def hasVariants(self): def hasVariants(self):
# Todo: Still hardcoded. if self._global_container_stack:
# We should implement this properly when it's clear how a machine notifies us if it can handle variants return self._global_container_stack.getMetaDataEntry("has_variants", False)
return True
return False
def createMachineManagerModel(engine, script_engine): def createMachineManagerModel(engine, script_engine):
return MachineManagerModel() return MachineManagerModel()

View File

@ -57,7 +57,8 @@ class CuraEngineBackend(Backend):
#When any setting property changed, call the _onSettingChanged function. #When any setting property changed, call the _onSettingChanged function.
#This function will then see if we need to start slicing. #This function will then see if we need to start slicing.
Application.getInstance().getGlobalContainerStack().propertyChanged.connect(self._onSettingChanged) if Application.getInstance().getGlobalContainerStack():
Application.getInstance().getGlobalContainerStack().propertyChanged.connect(self._onSettingChanged)
#When you update a setting and other settings get changed through inheritance, many propertyChanged signals are fired. #When you update a setting and other settings get changed through inheritance, many propertyChanged signals are fired.
#This timer will group them up, and only slice for the last setting changed signal. #This timer will group them up, and only slice for the last setting changed signal.

View File

@ -2,10 +2,16 @@
# Cura is released under the terms of the AGPLv3 or higher. # Cura is released under the terms of the AGPLv3 or higher.
import math import math
import copy
import xml.etree.ElementTree as ET import xml.etree.ElementTree as ET
from UM.Logger import Logger
import UM.Settings import UM.Settings
# The namespace is prepended to the tag name but between {}.
# We are only interested in the actual tag name, so discard everything
# before the last }
def _tag_without_namespace(element): def _tag_without_namespace(element):
return element.tag[element.tag.rfind("}") + 1:] return element.tag[element.tag.rfind("}") + 1:]
@ -17,7 +23,6 @@ class XmlMaterialProfile(UM.Settings.InstanceContainer):
raise NotImplementedError("Writing material profiles has not yet been implemented") raise NotImplementedError("Writing material profiles has not yet been implemented")
def deserialize(self, serialized): def deserialize(self, serialized):
print("deserialize material profile")
data = ET.fromstring(serialized) data = ET.fromstring(serialized)
self.addMetaDataEntry("type", "material") self.addMetaDataEntry("type", "material")
@ -27,9 +32,7 @@ class XmlMaterialProfile(UM.Settings.InstanceContainer):
metadata = data.iterfind("./um:metadata/*", self.__namespaces) metadata = data.iterfind("./um:metadata/*", self.__namespaces)
for entry in metadata: for entry in metadata:
# The namespace is prepended to the tag name but between {}. tag_name = _tag_without_namespace(entry)
# We are only interested in the actual tag name.
tag_name = entry.tag[entry.tag.rfind("}") + 1:]
if tag_name == "name": if tag_name == "name":
brand = entry.find("./um:brand", self.__namespaces) brand = entry.find("./um:brand", self.__namespaces)
@ -47,7 +50,7 @@ class XmlMaterialProfile(UM.Settings.InstanceContainer):
property_values = {} property_values = {}
properties = data.iterfind("./um:properties/*", self.__namespaces) properties = data.iterfind("./um:properties/*", self.__namespaces)
for entry in properties: for entry in properties:
tag_name = entry.tag[entry.tag.rfind("}") + 1:] tag_name = _tag_without_namespace(entry)
property_values[tag_name] = entry.text property_values[tag_name] = entry.text
diameter = float(property_values.get("diameter", 2.85)) # In mm diameter = float(property_values.get("diameter", 2.85)) # In mm
@ -66,12 +69,50 @@ class XmlMaterialProfile(UM.Settings.InstanceContainer):
self.addMetaDataEntry("properties", property_values) self.addMetaDataEntry("properties", property_values)
global_setting_values = {}
settings = data.iterfind("./um:settings/um:setting", self.__namespaces) settings = data.iterfind("./um:settings/um:setting", self.__namespaces)
for entry in settings: for entry in settings:
tag_name = _tag_without_namespace(entry) key = entry.get("key")
if key in self.__material_property_setting_map:
self.setProperty(self.__material_property_setting_map[key], "value", entry.text, self._definition)
global_setting_values[key] = entry.text
machines = data.iterfind("./um:settings/um:machine", self.__namespaces)
for machine in machines:
machine_setting_values = {}
settings = machine.iterfind("./um:setting", self.__namespaces)
for entry in settings:
key = entry.get("key")
if key in self.__material_property_setting_map:
machine_setting_values[self.__material_property_setting_map[key]] = entry.text
identifiers = machine.iterfind("./um:machine_identifier", self.__namespaces)
for identifier in identifiers:
machine_id = self.__product_id_map.get(identifier.get("product"), None)
if machine_id is None:
Logger.log("w", "Cannot create material for unknown machine %s", machine_id)
continue
definitions = UM.Settings.ContainerRegistry.getInstance().findDefinitionContainers(id = machine_id)
if not definitions:
Logger.log("w", "No definition found for machine ID %s", machine_id)
continue
new_material = XmlMaterialProfile(self.id + "_" + machine_id)
new_material.setName(self.getName())
new_material.setMetaData(self.getMetaData())
new_material.setDefinition(definitions[0])
for key, value in global_setting_values.items():
new_material.setProperty(key, "value", value, definitions[0])
for key, value in machine_setting_values.items():
new_material.setProperty(key, "value", value, definitions[0])
new_material._dirty = False
UM.Settings.ContainerRegistry.getInstance().addContainer(new_material)
if tag_name in self.__material_property_setting_map:
self.setProperty(self.__material_property_setting_map[tag_name], "value", entry.text)
__material_property_setting_map = { __material_property_setting_map = {
"print temperature": "material_print_temperature", "print temperature": "material_print_temperature",
@ -79,6 +120,16 @@ class XmlMaterialProfile(UM.Settings.InstanceContainer):
"standby temperature": "material_standby_temperature", "standby temperature": "material_standby_temperature",
} }
__product_id_map = {
"Ultimaker2": "ultimaker2",
"Ultimaker2+": "ultimaker2_plus",
"Ultimaker2go": "ultimaker2_go",
"Ultimaker2extended": "ultimaker2_extended",
"Ultimaker2extended+": "ultimaker2_extended_plus",
"Ultimaker Original": "ultimaker_original",
"Ultimaker Original+": "ultimaker_original_plus"
}
__namespaces = { __namespaces = {
"um": "http://www.ultimaker.com/material" "um": "http://www.ultimaker.com/material"
} }

View File

@ -10,7 +10,10 @@
"category": "Ultimaker", "category": "Ultimaker",
"file_formats": "text/x-gcode", "file_formats": "text/x-gcode",
"platform": "ultimaker2_platform.obj", "platform": "ultimaker2_platform.obj",
"platform_texture": "Ultimaker2Plusbackplate.png" "platform_texture": "Ultimaker2Plusbackplate.png",
"preferred_variant": "ultimaker2_plus_0.4",
"preferred_material": "pla",
"preferred_quality": "high"
}, },
"overrides": { "overrides": {

View File

@ -16,7 +16,6 @@ Generic PLA profile. Serves as an example file, data in this file is not correct
<properties> <properties>
<density>1.3</density> <density>1.3</density>
<diameter>2.85</diameter> <diameter>2.85</diameter>
<spool_weight>750</spool_weight>
</properties> </properties>
<settings> <settings>
<setting key="print temperature">210</setting> <setting key="print temperature">210</setting>
@ -24,9 +23,8 @@ Generic PLA profile. Serves as an example file, data in this file is not correct
<setting key="standby temperature">175</setting> <setting key="standby temperature">175</setting>
<machine> <machine>
<machine_identifier manufacturer="Ultimaker" product="Ultimaker2"/> <machine_identifier manufacturer="Ultimaker" product="Ultimaker2+"/>
<machine_identifier manufacturer="Ultimaker" product="Ultimaker2go"/> <machine_identifier manufacturer="Ultimaker" product="Ultimaker2extended+"/>
<machine_identifier manufacturer="Ultimaker" product="Ultimaker2extended"/>
<setting key="standby temperature">150</setting> <setting key="standby temperature">150</setting>
<setting key="processing temperature graph"> <setting key="processing temperature graph">
<point flow="2" temperature="180"/> <point flow="2" temperature="180"/>
@ -36,6 +34,7 @@ Generic PLA profile. Serves as an example file, data in this file is not correct
<machine> <machine>
<machine_identifier manufacturer="Ultimaker" product="Ultimaker Original"/> <machine_identifier manufacturer="Ultimaker" product="Ultimaker Original"/>
<machine_identifier manufacturer="Ultimaker" product="Ultimaker Original+"/>
<setting key="standby temperature">150</setting> <setting key="standby temperature">150</setting>
<hotend id="0.8mm"> <hotend id="0.8mm">
<setting key="standby temperature">80</setting> <setting key="standby temperature">80</setting>

View File

@ -813,9 +813,8 @@ UM.MainWindow
base.visible = true; base.visible = true;
restart(); restart();
} }
else if(Cura.MachineManager.activeMachineName == "") else if(Cura.MachineManager.activeMachineId == null || Cura.MachineManager.activeMachineId == "")
{ {
addMachineDialog.firstRun = true;
addMachineDialog.open(); addMachineDialog.open();
} }
} }

View File

@ -6,6 +6,7 @@ import QtQuick.Controls 1.1
import QtQuick.Dialogs 1.2 import QtQuick.Dialogs 1.2
import UM 1.2 as UM import UM 1.2 as UM
import Cura 1.0 as Cura
UM.ManagementPage UM.ManagementPage
{ {
@ -13,7 +14,7 @@ UM.ManagementPage
title: catalog.i18nc("@title:tab", "Materials"); title: catalog.i18nc("@title:tab", "Materials");
model: UM.InstanceContainersModel { filter: { "type": "material" } } model: UM.InstanceContainersModel { filter: { "type": "material", "definition": Cura.MachineManager.activeDefinitionId } }
/* /*
onAddObject: { var selectedMaterial = UM.MaterialManager.createProfile(); base.selectMaterial(selectedMaterial); } onAddObject: { var selectedMaterial = UM.MaterialManager.createProfile(); base.selectMaterial(selectedMaterial); }
onRemoveObject: confirmDialog.open(); onRemoveObject: confirmDialog.open();

View File

@ -197,7 +197,7 @@ Item
id: materialSelectionInstantiator id: materialSelectionInstantiator
model: UM.InstanceContainersModel model: UM.InstanceContainersModel
{ {
filter: {"type": "material"} filter: { "type": "material", "definition": Cura.MachineManager.activeDefinitionId }
} }
MenuItem MenuItem
{ {

View File

@ -7,3 +7,4 @@ definition = fdmprinter
type = quality type = quality
[values] [values]
layer_height = 0.06