From 2c8b9290f84e7671c0cc6e421a1bea8ae3852000 Mon Sep 17 00:00:00 2001 From: Jaime van Kessel Date: Wed, 31 Aug 2016 11:41:33 +0200 Subject: [PATCH 01/13] Made checking if inheritance is allowed more explicit CURA-2108 --- cura/Settings/MachineManager.py | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) diff --git a/cura/Settings/MachineManager.py b/cura/Settings/MachineManager.py index 348ce6a49c..91cfd5e811 100644 --- a/cura/Settings/MachineManager.py +++ b/cura/Settings/MachineManager.py @@ -838,15 +838,16 @@ class MachineManager(QObject): # that are assigned to the parents of this material profile. try: inherited_files = material_container.getInheritedFiles() - if inherited_files: - for inherited_file in inherited_files: - # Extract the ID from the path we used to load the file. - search_criteria["material"] = os.path.basename(inherited_file).split(".")[0] - containers = container_registry.findInstanceContainers(**search_criteria) - if containers: - return containers[0] except AttributeError: # Material_container does not support inheritance. - pass + inherited_files = [] + + if inherited_files: + for inherited_file in inherited_files: + # Extract the ID from the path we used to load the file. + search_criteria["material"] = os.path.basename(inherited_file).split(".")[0] + containers = container_registry.findInstanceContainers(**search_criteria) + if containers: + return containers[0] # We still weren't able to find a quality for this specific material. # Try to find qualities for a generic version of the material. From 57f13869e61d8ec4ccf63b6b44ab830a87c92237 Mon Sep 17 00:00:00 2001 From: Jack Ha Date: Wed, 31 Aug 2016 12:47:21 +0200 Subject: [PATCH 02/13] For the beta release, removed duplicate and import material. --- resources/qml/Preferences/MaterialsPage.qml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/resources/qml/Preferences/MaterialsPage.qml b/resources/qml/Preferences/MaterialsPage.qml index 6804128381..486b67f3a5 100644 --- a/resources/qml/Preferences/MaterialsPage.qml +++ b/resources/qml/Preferences/MaterialsPage.qml @@ -151,6 +151,7 @@ UM.ManagementPage Cura.MachineManager.setActiveMaterial(material_id) } + visible: false; }, Button { @@ -164,6 +165,7 @@ UM.ManagementPage text: catalog.i18nc("@action:button", "Import"); iconName: "document-import"; onClicked: importDialog.open(); + visible: false; }, Button { From c10f04d63877a986d225adc5b79a473a3a793412 Mon Sep 17 00:00:00 2001 From: Jack Ha Date: Wed, 31 Aug 2016 12:53:14 +0200 Subject: [PATCH 03/13] Typo in changelog --- plugins/ChangeLogPlugin/ChangeLog.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/ChangeLogPlugin/ChangeLog.txt b/plugins/ChangeLogPlugin/ChangeLog.txt index 08e89dca33..ad09470ccd 100644 --- a/plugins/ChangeLogPlugin/ChangeLog.txt +++ b/plugins/ChangeLogPlugin/ChangeLog.txt @@ -1,7 +1,7 @@ [2.3.0] *Speed improvements -The first thing you will notice iss the speed. STL loading is now 10 to 20 times faster, layer time is significantly faster and slicing speed is slightly improved. +The first thing you will notice is the speed. STL loading is now 10 to 20 times faster, layer time is significantly faster and slicing speed is slightly improved. *Multi Extrusion Support Machines with multiple extruders are now supported. If you’ve got the Ultimaker Original with the dual extrusion upgrade kit, we’ve got you covered. From 6ff258d7e074d6742fe271c73e48b1ce99ef887c Mon Sep 17 00:00:00 2001 From: Jaime van Kessel Date: Wed, 31 Aug 2016 14:52:41 +0200 Subject: [PATCH 04/13] Single extrusion machines now show correct values for profiles in tab CURA-2214 --- cura/Settings/QualitySettingsModel.py | 1 - resources/qml/Preferences/ProfilesPage.qml | 2 +- 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/cura/Settings/QualitySettingsModel.py b/cura/Settings/QualitySettingsModel.py index b768b1543a..64052fe4e3 100644 --- a/cura/Settings/QualitySettingsModel.py +++ b/cura/Settings/QualitySettingsModel.py @@ -182,7 +182,6 @@ class QualitySettingsModel(UM.Qt.ListModel.ListModel): # If a setting is settable per extruder (not global) and we're looking at global tab, don't show this value. if self._extruder_id == "" and settable_per_extruder: continue - items.append({ "key": definition.key, "label": definition.label, diff --git a/resources/qml/Preferences/ProfilesPage.qml b/resources/qml/Preferences/ProfilesPage.qml index 4d9b2f7b2c..4a0d87b812 100644 --- a/resources/qml/Preferences/ProfilesPage.qml +++ b/resources/qml/Preferences/ProfilesPage.qml @@ -212,7 +212,7 @@ UM.ManagementPage { title: catalog.i18nc("@title:tab", "Global Settings"); quality: base.currentItem != null ? base.currentItem.id : ""; - material: Cura.MachineManager.allActiveMaterialIds.global ? Cura.MachineManager.allActiveMaterialIds.global : "" + material: Cura.MachineManager.allActiveMaterialIds[Cura.MachineManager.activeMachineId] } Repeater From 1fda24c43fc9254f79eefc2bbf000576f7daa203 Mon Sep 17 00:00:00 2001 From: Jaime van Kessel Date: Wed, 31 Aug 2016 15:09:04 +0200 Subject: [PATCH 05/13] Removed dead code CURA-2108 --- plugins/XmlMaterialProfile/XmlMaterialProfile.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/XmlMaterialProfile/XmlMaterialProfile.py b/plugins/XmlMaterialProfile/XmlMaterialProfile.py index b5337258e5..563ea4a303 100644 --- a/plugins/XmlMaterialProfile/XmlMaterialProfile.py +++ b/plugins/XmlMaterialProfile/XmlMaterialProfile.py @@ -305,7 +305,7 @@ class XmlMaterialProfile(UM.Settings.InstanceContainer): # TODO: Add material verfication self.addMetaDataEntry("status", "unknown") - #for inherit in data.findall("./um:inherits", self.__namespaces): + inherits = data.find("./um:inherits", self.__namespaces) if inherits is not None: inherited = self._resolveInheritance(inherits.text) From e9d9597caa9002ca52ad5c99ab6b503f768b50ce Mon Sep 17 00:00:00 2001 From: Jack Ha Date: Thu, 1 Sep 2016 11:22:38 +0200 Subject: [PATCH 06/13] Commented out duplicate and import, on OS X 'visible' does not work --- resources/qml/Preferences/MaterialsPage.qml | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/resources/qml/Preferences/MaterialsPage.qml b/resources/qml/Preferences/MaterialsPage.qml index 486b67f3a5..d2d7c1b0a2 100644 --- a/resources/qml/Preferences/MaterialsPage.qml +++ b/resources/qml/Preferences/MaterialsPage.qml @@ -129,6 +129,7 @@ UM.ManagementPage enabled: base.currentItem != null && base.currentItem.id != Cura.MachineManager.activeMaterialId onClicked: Cura.MachineManager.setActiveMaterial(base.currentItem.id) }, + /* // apparently visible does not work on OS X Button { text: catalog.i18nc("@action:button", "Duplicate"); @@ -153,6 +154,7 @@ UM.ManagementPage } visible: false; }, + */ Button { 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) onClicked: confirmDialog.open() }, + /* // apparently visible does not work on OS X Button { text: catalog.i18nc("@action:button", "Import"); @@ -167,6 +170,7 @@ UM.ManagementPage onClicked: importDialog.open(); visible: false; }, + */ Button { text: catalog.i18nc("@action:button", "Export") From bacac1e42e48e240ed2e6e71df999c7e54933de2 Mon Sep 17 00:00:00 2001 From: Jaime van Kessel Date: Wed, 31 Aug 2016 17:18:33 +0200 Subject: [PATCH 07/13] XML material profile merging is now far less naive. It's still a work in progress, as it doesn't succeed in all cases just yet. CURA-2108 --- .../XmlMaterialProfile/XmlMaterialProfile.py | 70 +++++++++++++------ 1 file changed, 48 insertions(+), 22 deletions(-) diff --git a/plugins/XmlMaterialProfile/XmlMaterialProfile.py b/plugins/XmlMaterialProfile/XmlMaterialProfile.py index 563ea4a303..15f022d539 100644 --- a/plugins/XmlMaterialProfile/XmlMaterialProfile.py +++ b/plugins/XmlMaterialProfile/XmlMaterialProfile.py @@ -58,9 +58,9 @@ class XmlMaterialProfile(UM.Settings.InstanceContainer): def setReadOnly(self, 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): - container._read_only = read_only + container._read_only = read_only # prevent loop instead of calling setReadOnly ## Overridden from InstanceContainer def setMetaDataEntry(self, key, value): @@ -69,7 +69,7 @@ class XmlMaterialProfile(UM.Settings.InstanceContainer): 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 for container in UM.Settings.ContainerRegistry.getInstance().findInstanceContainers(base_file = basefile): container.setMetaData(copy.deepcopy(self._metadata)) @@ -95,15 +95,15 @@ class XmlMaterialProfile(UM.Settings.InstanceContainer): container.setName(new_name) ## Overridden from InstanceContainer - def setProperty(self, key, property_name, property_value, container = None): - if self.isReadOnly(): - return - - super().setProperty(key, property_name, property_value) - - basefile = self.getMetaDataEntry("base_file", self._id) #if basefile is none, this is a basefile. - for container in UM.Settings.ContainerRegistry.getInstance().findInstanceContainers(base_file = basefile): - container._dirty = True + # def setProperty(self, key, property_name, property_value, container = None): + # if self.isReadOnly(): + # return + # + # super().setProperty(key, property_name, property_value) + # + # 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): + # container._dirty = True ## Overridden from InstanceContainer def serialize(self): @@ -277,24 +277,50 @@ class XmlMaterialProfile(UM.Settings.InstanceContainer): self._combineElement(result, second) 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. # If it does not exist, copies it from second. def _combineElement(self, first, second): # Create a mapping from tag name to element. - mapping = {el.tag: el for el in first} - for el in second: - if len(el): # Check if element has children. + + mapping = {} + 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: - 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: - mapping[el.tag] = el - first.append(el) + mapping[key] = element + first.append(element) else: try: - mapping[el.tag].text = el.text + mapping[key].text = element.text except KeyError: # Not in the mapping, so simply add it - mapping[el.tag] = el - first.append(el) + mapping[key] = element + first.append(element) ## Overridden from InstanceContainer def deserialize(self, serialized): @@ -305,7 +331,7 @@ class XmlMaterialProfile(UM.Settings.InstanceContainer): # TODO: Add material verfication self.addMetaDataEntry("status", "unknown") - + inherits = data.find("./um:inherits", self.__namespaces) if inherits is not None: inherited = self._resolveInheritance(inherits.text) From bef410b4a34ded4a439e8db5263cd7ba87d9a5ed Mon Sep 17 00:00:00 2001 From: Jaime van Kessel Date: Thu, 1 Sep 2016 11:18:15 +0200 Subject: [PATCH 08/13] Machines are now flattened before merging them This ensures that machines are overwritten correctly CURA-2108 --- .../XmlMaterialProfile/XmlMaterialProfile.py | 37 ++++++++++++++++++- ...maker_pla_silver-metallic.xml.fdm_material | 8 ++-- 2 files changed, 40 insertions(+), 5 deletions(-) diff --git a/plugins/XmlMaterialProfile/XmlMaterialProfile.py b/plugins/XmlMaterialProfile/XmlMaterialProfile.py index 15f022d539..58a948c17b 100644 --- a/plugins/XmlMaterialProfile/XmlMaterialProfile.py +++ b/plugins/XmlMaterialProfile/XmlMaterialProfile.py @@ -272,9 +272,44 @@ class XmlMaterialProfile(UM.Settings.InstanceContainer): self._inherited_files.append(path) 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): result = copy.deepcopy(first) - self._combineElement(result, second) + self._combineElement(self._flattenMachinesXML(result), self._flattenMachinesXML(second)) return result def _createKey(self, element): diff --git a/resources/materials/ultimaker_pla_silver-metallic.xml.fdm_material b/resources/materials/ultimaker_pla_silver-metallic.xml.fdm_material index fd829abf6c..2f250e8e31 100644 --- a/resources/materials/ultimaker_pla_silver-metallic.xml.fdm_material +++ b/resources/materials/ultimaker_pla_silver-metallic.xml.fdm_material @@ -3,6 +3,7 @@ Automatically generated PLA profile. Data in this file may not be not correct. --> + generic_pla Ultimaker @@ -36,16 +37,15 @@ Automatically generated PLA profile. Data in this file may not be not correct. - 150 - - + + - 150 + 180 From d8c7b325f0bd17a3090696532103dc017af86869 Mon Sep 17 00:00:00 2001 From: Barry Stump Date: Wed, 31 Aug 2016 14:58:46 -0700 Subject: [PATCH 09/13] update Printrbot Simple definition * Add platform mesh * Default nozzle size is 0.4mm * Updated start gcode to correct bed origin after auto-level --- resources/definitions/printrbot_simple.def.json | 7 ++++--- .../meshes/printrbot_simple_metal_platform.stl | Bin 0 -> 33284 bytes 2 files changed, 4 insertions(+), 3 deletions(-) create mode 100644 resources/meshes/printrbot_simple_metal_platform.stl diff --git a/resources/definitions/printrbot_simple.def.json b/resources/definitions/printrbot_simple.def.json index a1963fe20e..255259df5a 100644 --- a/resources/definitions/printrbot_simple.def.json +++ b/resources/definitions/printrbot_simple.def.json @@ -8,6 +8,7 @@ "author": "Calvindog717", "manufacturer": "PrintrBot", "category": "Other", + "platform": "printrbot_simple_metal_platform.stl", "file_formats": "text/x-gcode" }, @@ -17,7 +18,7 @@ "machine_height": { "default_value": 150 }, "machine_depth": { "default_value": 140 }, "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 }, "machine_nozzle_heat_up_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_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": { - "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" } } } diff --git a/resources/meshes/printrbot_simple_metal_platform.stl b/resources/meshes/printrbot_simple_metal_platform.stl new file mode 100644 index 0000000000000000000000000000000000000000..717d224f1fd75ed6b9e95cf9ffb71d496eb8aae1 GIT binary patch literal 33284 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 Date: Thu, 1 Sep 2016 13:00:54 +0200 Subject: [PATCH 10/13] Setting state is now set to calculated after setting the value This ensures that the setting of the value does not overide the state CURA-2221 --- resources/qml/Settings/SettingItem.qml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/resources/qml/Settings/SettingItem.qml b/resources/qml/Settings/SettingItem.qml index 449a244b80..ed16b722dd 100644 --- a/resources/qml/Settings/SettingItem.qml +++ b/resources/qml/Settings/SettingItem.qml @@ -246,8 +246,8 @@ Item { // 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 // defaults. - propertyProvider.setPropertyValue("state", "InstanceState.Calculated") propertyProvider.setPropertyValue("value", propertyProvider.getPropertyValue("value", last_entry)) + propertyProvider.setPropertyValue("state", "InstanceState.Calculated") } } From fa3464901ee2476c3e2eeb0cb650cbe1a7d976fe Mon Sep 17 00:00:00 2001 From: fieldOfView Date: Thu, 1 Sep 2016 13:03:50 +0200 Subject: [PATCH 11/13] Only show prime tower disabled area when the prime tower is enabled CURA-2152 --- cura/BuildVolume.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cura/BuildVolume.py b/cura/BuildVolume.py index 2acdd053bb..a91a85f406 100644 --- a/cura/BuildVolume.py +++ b/cura/BuildVolume.py @@ -303,7 +303,7 @@ class BuildVolume(SceneNode): machine_depth = self._global_container_stack.getProperty("machine_depth", "value") # Add prime tower location as disallowed area. - if self._global_container_stack.getProperty("prime_tower_enable", "value"): + if self._global_container_stack.getProperty("prime_tower_enable", "value") == True: prime_tower_size = self._global_container_stack.getProperty("prime_tower_size", "value") prime_tower_x = self._global_container_stack.getProperty("prime_tower_position_x", "value") - machine_width / 2 prime_tower_y = - self._global_container_stack.getProperty("prime_tower_position_y", "value") + machine_depth / 2 From aa689dc2fb1fc1cd8207b8d2b54768d6c02b9979 Mon Sep 17 00:00:00 2001 From: fieldOfView Date: Thu, 1 Sep 2016 13:34:18 +0200 Subject: [PATCH 12/13] Fix layerview for grouped objects The "ghosts" would be rendered over grouped objects, thereby making them not visible. Note that this quick fix comes at the price of slightly "muddying" all the layerview colors. A better fix was proposed here (but it is not yet working correctly): https://github.com/Ultimaker/Cura/pull/906 CURA-2246 --- plugins/LayerView/LayerView.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/plugins/LayerView/LayerView.py b/plugins/LayerView/LayerView.py index 791ca0e153..801f4797dd 100644 --- a/plugins/LayerView/LayerView.py +++ b/plugins/LayerView/LayerView.py @@ -86,7 +86,7 @@ class LayerView(View): if not self._ghost_shader: self._ghost_shader = OpenGL.getInstance().createShaderProgram(Resources.getPath(Resources.Shaders, "color.shader")) - self._ghost_shader.setUniformValue("u_color", Color(0, 0, 0, 72)) + self._ghost_shader.setUniformValue("u_color", Color(0, 0, 0, 64)) for node in DepthFirstIterator(scene.getRoot()): # We do not want to render ConvexHullNode as it conflicts with the bottom layers. @@ -98,10 +98,10 @@ class LayerView(View): if node.getMeshData() and node.isVisible(): renderer.queueNode(node, shader = self._ghost_shader, - state_setup_callback = lambda gl: gl.glDepthMask(gl.GL_FALSE), - state_teardown_callback = lambda gl: gl.glDepthMask(gl.GL_TRUE) - ) + type = RenderBatch.RenderType.Transparent ) + for node in DepthFirstIterator(scene.getRoot()): + if type(node) is SceneNode: if node.getMeshData() and node.isVisible(): layer_data = node.callDecoration("getLayerData") if not layer_data: From a2f478f2ad9df16e62f40406cf913957d3fac3f1 Mon Sep 17 00:00:00 2001 From: Simon Edwards Date: Thu, 1 Sep 2016 13:48:46 +0200 Subject: [PATCH 13/13] Fix for "Creating two profiles causes the names to become messed up" CURA-2220 --- cura/Settings/ContainerManager.py | 17 +++-- resources/qml/Cura.qml | 2 +- resources/qml/Preferences/ProfilesPage.qml | 74 ++++++++++++++++------ 3 files changed, 67 insertions(+), 26 deletions(-) diff --git a/cura/Settings/ContainerManager.py b/cura/Settings/ContainerManager.py index e220a5f2f1..1e0ac3338f 100644 --- a/cura/Settings/ContainerManager.py +++ b/cura/Settings/ContainerManager.py @@ -423,8 +423,8 @@ class ContainerManager(QObject): # stack and clear the user settings. # # \return \type{bool} True if the operation was successfully, False if not. - @pyqtSlot(result = bool) - def createQualityChanges(self): + @pyqtSlot(str, result = bool) + def createQualityChanges(self, base_name): global_stack = UM.Application.getInstance().getGlobalContainerStack() if not global_stack: return False @@ -436,7 +436,9 @@ class ContainerManager(QObject): self._machine_manager.blurSettings.emit() - unique_name = self._container_registry.uniqueName(active_quality_name) + if base_name is None: + base_name = active_quality_name + unique_name = self._container_registry.uniqueName(base_name) # Go through the active stacks and create quality_changes containers from the user containers. for stack in cura.Settings.ExtruderManager.getInstance().getActiveGlobalAndExtruderStacks(): @@ -540,8 +542,8 @@ class ContainerManager(QObject): # \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): + @pyqtSlot(str, str, result = str) + def duplicateQualityOrQualityChanges(self, quality_name, base_name): global_stack = UM.Application.getInstance().getGlobalContainerStack() if not global_stack or not quality_name: return "" @@ -551,7 +553,10 @@ class ContainerManager(QObject): UM.Logger.log("d", "Unable to duplicate the quality %s, because it doesn't exist.", quality_name) return "" - new_name = self._container_registry.uniqueName(quality_name) + if base_name is None: + base_name = quality_name + + new_name = self._container_registry.uniqueName(base_name) container_type = containers[0].getMetaDataEntry("type") if container_type == "quality": diff --git a/resources/qml/Cura.qml b/resources/qml/Cura.qml index 5ba0c82f00..34dbcf1b67 100644 --- a/resources/qml/Cura.qml +++ b/resources/qml/Cura.qml @@ -463,7 +463,7 @@ UM.MainWindow target: Cura.Actions.addProfile onTriggered: { - Cura.ContainerManager.createQualityChanges(); + Cura.ContainerManager.createQualityChanges(null); preferences.setPage(4); preferences.show(); diff --git a/resources/qml/Preferences/ProfilesPage.qml b/resources/qml/Preferences/ProfilesPage.qml index 4a0d87b812..15e46a9dda 100644 --- a/resources/qml/Preferences/ProfilesPage.qml +++ b/resources/qml/Preferences/ProfilesPage.qml @@ -61,6 +61,10 @@ UM.ManagementPage return -1; } + function canCreateProfile() { + return base.currentItem && (base.currentItem.id == Cura.MachineManager.activeQualityId) && Cura.MachineManager.hasUserSettings; + } + buttons: [ Button { @@ -69,26 +73,39 @@ UM.ManagementPage enabled: base.currentItem != null ? base.currentItem.id != Cura.MachineManager.activeQualityId : false; onClicked: Cura.MachineManager.setActiveQuality(base.currentItem.id) }, + + // Create button Button { - text: base.currentItem && (base.currentItem.id == Cura.MachineManager.activeQualityId) && Cura.MachineManager.hasUserSettings ? catalog.i18nc("@label", "Create") : catalog.i18nc("@label", "Duplicate") + text: catalog.i18nc("@label", "Create") + enabled: base.canCreateProfile() + visible: base.canCreateProfile() iconName: "list-add"; onClicked: { - var selectedContainer; - if (base.currentItem.id == Cura.MachineManager.activeQualityId && Cura.MachineManager.hasUserSettings) { - selectedContainer = Cura.ContainerManager.createQualityChanges(); - } else { - selectedContainer = Cura.ContainerManager.duplicateQualityOrQualityChanges(base.currentItem.name); - } - base.selectContainer(selectedContainer); - - renameDialog.removeWhenRejected = true; - renameDialog.open(); - renameDialog.selectText(); + newNameDialog.object = base.currentItem != null ? base.currentItem.name : ""; + newNameDialog.open(); + newNameDialog.selectText(); } }, + + // Duplicate button + Button + { + text: catalog.i18nc("@label", "Duplicate") + enabled: ! base.canCreateProfile() + visible: ! base.canCreateProfile() + iconName: "list-add"; + + onClicked: + { + newDuplicateNameDialog.object = base.currentItem.name; + newDuplicateNameDialog.open(); + newDuplicateNameDialog.selectText(); + } + }, + Button { text: catalog.i18nc("@action:button", "Remove"); @@ -103,7 +120,6 @@ UM.ManagementPage enabled: base.currentItem != null ? !base.currentItem.readOnly : false; onClicked: { - renameDialog.removeWhenRejected = false; renameDialog.open(); renameDialog.selectText(); } @@ -249,24 +265,44 @@ UM.ManagementPage objectList.currentIndex = -1 //Reset selection. } } + UM.RenameDialog { id: renameDialog; object: base.currentItem != null ? base.currentItem.name : "" - property bool removeWhenRejected: false onAccepted: { Cura.ContainerManager.renameQualityChanges(base.currentItem.name, newName) objectList.currentIndex = -1 //Reset selection. } - onRejected: + } + + // Dialog to request a name when creating a new profile + UM.RenameDialog + { + id: newNameDialog; + object: ""; + onAccepted: { - if(removeWhenRejected) - { - Cura.ContainerManager.removeQualityChanges(base.currentItem.name) - } + var selectedContainer = Cura.ContainerManager.createQualityChanges(newName); + base.selectContainer(selectedContainer); + objectList.currentIndex = -1 //Reset selection. } } + + // Dialog to request a name when duplicating a new profile + UM.RenameDialog + { + id: newDuplicateNameDialog; + object: ""; + onAccepted: + { + var selectedContainer = Cura.ContainerManager.duplicateQualityOrQualityChanges(base.currentItem.name, newName); + base.selectContainer(selectedContainer); + objectList.currentIndex = -1 //Reset selection. + } + } + MessageDialog { id: messageDialog