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

This commit is contained in:
fieldOfView 2016-09-01 13:04:09 +02:00
commit 73d7e22efe
6 changed files with 97 additions and 31 deletions

View File

@ -58,9 +58,9 @@ class XmlMaterialProfile(UM.Settings.InstanceContainer):
def setReadOnly(self, read_only): def setReadOnly(self, read_only):
super().setReadOnly(read_only) super().setReadOnly(read_only)
basefile = self.getMetaDataEntry("base_file", self._id) #if basefile is none, this is a basefile. basefile = self.getMetaDataEntry("base_file", self._id) # if basefile is self.id, this is a basefile.
for container in UM.Settings.ContainerRegistry.getInstance().findInstanceContainers(base_file = basefile): for container in UM.Settings.ContainerRegistry.getInstance().findInstanceContainers(base_file = basefile):
container._read_only = read_only container._read_only = read_only # prevent loop instead of calling setReadOnly
## Overridden from InstanceContainer ## Overridden from InstanceContainer
def setMetaDataEntry(self, key, value): def setMetaDataEntry(self, key, value):
@ -69,7 +69,7 @@ class XmlMaterialProfile(UM.Settings.InstanceContainer):
super().setMetaDataEntry(key, value) super().setMetaDataEntry(key, value)
basefile = self.getMetaDataEntry("base_file", self._id) #if basefile is none, this is a basefile. basefile = self.getMetaDataEntry("base_file", self._id) #if basefile is self.id, this is a basefile.
# Update all containers that share GUID and basefile # Update all containers that share GUID and basefile
for container in UM.Settings.ContainerRegistry.getInstance().findInstanceContainers(base_file = basefile): for container in UM.Settings.ContainerRegistry.getInstance().findInstanceContainers(base_file = basefile):
container.setMetaData(copy.deepcopy(self._metadata)) container.setMetaData(copy.deepcopy(self._metadata))
@ -95,15 +95,15 @@ class XmlMaterialProfile(UM.Settings.InstanceContainer):
container.setName(new_name) container.setName(new_name)
## Overridden from InstanceContainer ## Overridden from InstanceContainer
def setProperty(self, key, property_name, property_value, container = None): # def setProperty(self, key, property_name, property_value, container = None):
if self.isReadOnly(): # if self.isReadOnly():
return # return
#
super().setProperty(key, property_name, property_value) # super().setProperty(key, property_name, property_value)
#
basefile = self.getMetaDataEntry("base_file", self._id) #if basefile is none, this is a basefile. # basefile = self.getMetaDataEntry("base_file", self._id) #if basefile is self.id, this is a basefile.
for container in UM.Settings.ContainerRegistry.getInstance().findInstanceContainers(base_file = basefile): # for container in UM.Settings.ContainerRegistry.getInstance().findInstanceContainers(base_file = basefile):
container._dirty = True # container._dirty = True
## Overridden from InstanceContainer ## Overridden from InstanceContainer
def serialize(self): def serialize(self):
@ -272,29 +272,90 @@ class XmlMaterialProfile(UM.Settings.InstanceContainer):
self._inherited_files.append(path) self._inherited_files.append(path)
return ET.fromstring(contents) return ET.fromstring(contents)
# The XML material profile can have specific settings for machines.
# Some machines share profiles, so they are only created once.
# This function duplicates those elements so that each machine tag only has one identifier.
def _flattenMachinesXML(self, element):
settings_element = element.find("./um:settings", self.__namespaces)
machines = settings_element.iterfind("./um:machine", self.__namespaces)
machines_to_add = []
machines_to_remove = []
for machine in machines:
identifiers = list(machine.iterfind("./um:machine_identifier", self.__namespaces))
has_multiple_identifiers = len(identifiers) > 1
if has_multiple_identifiers:
# Multiple identifiers found. We need to create a new machine element and copy all it's settings there.
for identifier in identifiers:
new_machine = copy.deepcopy(machine)
# Create list of identifiers that need to be removed from the copied element.
other_identifiers = [self._createKey(other_identifier) for other_identifier in identifiers if other_identifier is not identifier]
# As we can only remove by exact object reference, we need to look through the identifiers of copied machine.
new_machine_identifiers = list(new_machine.iterfind("./um:machine_identifier", self.__namespaces))
for new_machine_identifier in new_machine_identifiers:
key = self._createKey(new_machine_identifier)
# Key was in identifiers to remove, so this element needs to be purged
if key in other_identifiers:
new_machine.remove(new_machine_identifier)
machines_to_add.append(new_machine)
machines_to_remove.append(machine)
else:
pass # Machine only has one identifier. Nothing to do.
# Remove & add all required machines.
for machine_to_remove in machines_to_remove:
settings_element.remove(machine_to_remove)
for machine_to_add in machines_to_add:
settings_element.append(machine_to_add)
return element
def _mergeXML(self, first, second): def _mergeXML(self, first, second):
result = copy.deepcopy(first) result = copy.deepcopy(first)
self._combineElement(result, second) self._combineElement(self._flattenMachinesXML(result), self._flattenMachinesXML(second))
return result return result
def _createKey(self, element):
key = element.tag.split("}")[-1]
if "key" in element.attrib:
key += " key:" + element.attrib["key"]
if "manufacturer" in element.attrib:
key += " manufacturer:" + element.attrib["manufacturer"]
if "product" in element.attrib:
key += " product:" + element.attrib["product"]
if key == "machine":
for item in element:
if "machine_identifier" in item.tag:
key += " " + item.attrib["product"]
return key
# Recursively merges XML elements. Updates either the text or children if another element is found in first. # Recursively merges XML elements. Updates either the text or children if another element is found in first.
# If it does not exist, copies it from second. # If it does not exist, copies it from second.
def _combineElement(self, first, second): def _combineElement(self, first, second):
# Create a mapping from tag name to element. # Create a mapping from tag name to element.
mapping = {el.tag: el for el in first}
for el in second: mapping = {}
if len(el): # Check if element has children. for element in first:
key = self._createKey(element)
mapping[key] = element
for element in second:
key = self._createKey(element)
if len(element): # Check if element has children.
try: try:
self._combineElement(mapping[el.tag], el) # Multiple elements, handle those. if "setting " in key:
# Setting can have points in it. In that case, delete all values and override them.
for child in list(mapping[key]):
mapping[key].remove(child)
for child in element:
mapping[key].append(child)
else:
self._combineElement(mapping[key], element) # Multiple elements, handle those.
except KeyError: except KeyError:
mapping[el.tag] = el mapping[key] = element
first.append(el) first.append(element)
else: else:
try: try:
mapping[el.tag].text = el.text mapping[key].text = element.text
except KeyError: # Not in the mapping, so simply add it except KeyError: # Not in the mapping, so simply add it
mapping[el.tag] = el mapping[key] = element
first.append(el) first.append(element)
## Overridden from InstanceContainer ## Overridden from InstanceContainer
def deserialize(self, serialized): def deserialize(self, serialized):
@ -305,7 +366,7 @@ class XmlMaterialProfile(UM.Settings.InstanceContainer):
# TODO: Add material verfication # TODO: Add material verfication
self.addMetaDataEntry("status", "unknown") self.addMetaDataEntry("status", "unknown")
inherits = data.find("./um:inherits", self.__namespaces) inherits = data.find("./um:inherits", self.__namespaces)
if inherits is not None: if inherits is not None:
inherited = self._resolveInheritance(inherits.text) inherited = self._resolveInheritance(inherits.text)

View File

@ -8,6 +8,7 @@
"author": "Calvindog717", "author": "Calvindog717",
"manufacturer": "PrintrBot", "manufacturer": "PrintrBot",
"category": "Other", "category": "Other",
"platform": "printrbot_simple_metal_platform.stl",
"file_formats": "text/x-gcode" "file_formats": "text/x-gcode"
}, },
@ -17,7 +18,7 @@
"machine_height": { "default_value": 150 }, "machine_height": { "default_value": 150 },
"machine_depth": { "default_value": 140 }, "machine_depth": { "default_value": 140 },
"machine_center_is_zero": { "default_value": false }, "machine_center_is_zero": { "default_value": false },
"machine_nozzle_size": { "default_value": 0.3 }, "machine_nozzle_size": { "default_value": 0.4 },
"material_diameter": { "default_value": 1.75 }, "material_diameter": { "default_value": 1.75 },
"machine_nozzle_heat_up_speed": { "default_value": 2 }, "machine_nozzle_heat_up_speed": { "default_value": 2 },
"machine_nozzle_cool_down_speed": { "default_value": 2 }, "machine_nozzle_cool_down_speed": { "default_value": 2 },
@ -33,10 +34,10 @@
"machine_gcode_flavor": { "default_value": "RepRap (Marlin/Sprinter)" }, "machine_gcode_flavor": { "default_value": "RepRap (Marlin/Sprinter)" },
"machine_start_gcode": { "machine_start_gcode": {
"default_value": "G21 ;metric values\nG90 ;absolute positioning\nM82 ;set extruder to absolute mode\nM107 ;start with the fan off\nG28 X0 Y0 ;move X/Y to min endstops\nG28 Z0 ;move Z to min endstops\nG29 ; auto bed-levelling\nG1 Z15.0 F9000 ;move the platform down 15mm\nG92 E0 ;zero the extruded length\nG1 F200 E3 ;extrude 3mm of feed stock\nG92 E0 ;zero the extruded length again\nG1 F9000\n;Put printing message on LCD screen\nM117 Printing..." "default_value": "G21 ;metric values\nG90 ;absolute positioning\nM82 ;set extruder to absolute mode\nM107 ;start with the fan off\nG28 X0 Y0 ;home X/Y\nG28 Z0 ;home Z\nG92 E0 ;zero the extruded length\nG29 ;initiate auto bed leveling sequence\nG92 X132.4 Y20 ;correct bed origin (G29 changes it)"
}, },
"machine_end_gcode": { "machine_end_gcode": {
"default_value": "M104 S0 ;extruder heater off\nM140 S0 ;heated bed heater off (if you have it)\nG91 ;relative positioning\nG1 E-1 F300 ;retract the filament a bit before lifting the nozzle, to release some of the pressure\nG1 Z+0.5 E-5 X-20 Y-20 F9000 ;move Z up a bit and retract filament even more\nG28 X0 Y0 ;move X/Y to min endstops, so the head is out of the way\nM84 ;steppers off\nG90 ;absolute positioning" "default_value": "M104 S0 ;extruder heater off\nM140 S0 ;heated bed heater off (if you have it)\nM106 S0 ;fan off\nG91 ;relative positioning\nG1 E-1 F300 ;retract the filament a bit\nG1 Z+1 E-5 F9000 ;move Z up a bit and retract even more\nG28 X0 Y0 ;home X/Y, so the head is out of the way\nM84 ;steppers off\nG90 ;absolute positioning"
} }
} }
} }

View File

@ -3,6 +3,7 @@
Automatically generated PLA profile. Data in this file may not be not correct. Automatically generated PLA profile. Data in this file may not be not correct.
--> -->
<fdmmaterial xmlns="http://www.ultimaker.com/material"> <fdmmaterial xmlns="http://www.ultimaker.com/material">
<inherits>generic_pla</inherits>
<metadata> <metadata>
<name> <name>
<brand>Ultimaker</brand> <brand>Ultimaker</brand>
@ -36,16 +37,15 @@ Automatically generated PLA profile. Data in this file may not be not correct.
<machine_identifier manufacturer="Ultimaker" product="Ultimaker 2"/> <machine_identifier manufacturer="Ultimaker" product="Ultimaker 2"/>
<machine_identifier manufacturer="Ultimaker" product="Ultimaker 2 Go"/> <machine_identifier manufacturer="Ultimaker" product="Ultimaker 2 Go"/>
<machine_identifier manufacturer="Ultimaker" product="Ultimaker 2 Extended"/> <machine_identifier manufacturer="Ultimaker" product="Ultimaker 2 Extended"/>
<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="20"/>
<point flow="10" temperature="230"/> <point flow="10" temperature="20"/>
</setting> </setting>
</machine> </machine>
<machine> <machine>
<machine_identifier manufacturer="Ultimaker" product="Ultimaker Original"/> <machine_identifier manufacturer="Ultimaker" product="Ultimaker Original"/>
<setting key="standby temperature">150</setting> <setting key="standby temperature">180</setting>
</machine> </machine>
</settings> </settings>
</fdmmaterial> </fdmmaterial>

Binary file not shown.

View File

@ -129,6 +129,7 @@ UM.ManagementPage
enabled: base.currentItem != null && base.currentItem.id != Cura.MachineManager.activeMaterialId enabled: base.currentItem != null && base.currentItem.id != Cura.MachineManager.activeMaterialId
onClicked: Cura.MachineManager.setActiveMaterial(base.currentItem.id) onClicked: Cura.MachineManager.setActiveMaterial(base.currentItem.id)
}, },
/* // apparently visible does not work on OS X
Button Button
{ {
text: catalog.i18nc("@action:button", "Duplicate"); text: catalog.i18nc("@action:button", "Duplicate");
@ -153,6 +154,7 @@ UM.ManagementPage
} }
visible: false; visible: false;
}, },
*/
Button Button
{ {
text: catalog.i18nc("@action:button", "Remove"); text: catalog.i18nc("@action:button", "Remove");
@ -160,6 +162,7 @@ UM.ManagementPage
enabled: base.currentItem != null && !base.currentItem.readOnly && !Cura.ContainerManager.isContainerUsed(base.currentItem.id) enabled: base.currentItem != null && !base.currentItem.readOnly && !Cura.ContainerManager.isContainerUsed(base.currentItem.id)
onClicked: confirmDialog.open() onClicked: confirmDialog.open()
}, },
/* // apparently visible does not work on OS X
Button Button
{ {
text: catalog.i18nc("@action:button", "Import"); text: catalog.i18nc("@action:button", "Import");
@ -167,6 +170,7 @@ UM.ManagementPage
onClicked: importDialog.open(); onClicked: importDialog.open();
visible: false; visible: false;
}, },
*/
Button Button
{ {
text: catalog.i18nc("@action:button", "Export") text: catalog.i18nc("@action:button", "Export")

View File

@ -246,8 +246,8 @@ Item {
// This ensures that the value in any of the deeper containers need not be removed, which is // This ensures that the value in any of the deeper containers need not be removed, which is
// needed for the reset button (which deletes the top value) to correctly go back to profile // needed for the reset button (which deletes the top value) to correctly go back to profile
// defaults. // defaults.
propertyProvider.setPropertyValue("state", "InstanceState.Calculated")
propertyProvider.setPropertyValue("value", propertyProvider.getPropertyValue("value", last_entry)) propertyProvider.setPropertyValue("value", propertyProvider.getPropertyValue("value", last_entry))
propertyProvider.setPropertyValue("state", "InstanceState.Calculated")
} }
} }