From 1db448d7d89de6a2f18327380a098c487e416935 Mon Sep 17 00:00:00 2001 From: Lipu Fei Date: Thu, 23 Nov 2017 13:04:03 +0100 Subject: [PATCH 01/24] Use the correct quality container for global stacks loaded from project files CURA-4613 --- plugins/3MFReader/ThreeMFWorkspaceReader.py | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/plugins/3MFReader/ThreeMFWorkspaceReader.py b/plugins/3MFReader/ThreeMFWorkspaceReader.py index 8e087611ef..65f026685b 100755 --- a/plugins/3MFReader/ThreeMFWorkspaceReader.py +++ b/plugins/3MFReader/ThreeMFWorkspaceReader.py @@ -790,6 +790,19 @@ class ThreeMFWorkspaceReader(WorkspaceReader): for stack in [global_stack] + extruder_stacks: stack.replaceContainer(_ContainerIndexes.Quality, empty_quality_container) + # Fix quality: + # The quality specified in an old project file can be wrong, for example, for UM2, it should be "um2_normal" + # but instead it was "normal". This should be fixed by setting it to the correct quality. + # Note that this only seems to happen on single-extrusion machines on the global stack, so we only apply the + # fix for that + quality = global_stack.quality + if quality.getId() not in ("empty", "empty_quality"): + quality_type = quality.getMetaDataEntry("quality_type") + quality_containers = self._container_registry.findInstanceContainers(definition = global_stack.definition.getId(), + quality_type = quality_type) + if quality_containers: + global_stack.quality = quality_containers[0] + # Replacing the old containers if resolve is "new". # When resolve is "new", some containers will get renamed, so all the other containers that reference to those # MUST get updated too. From 2397b68cd78bb40aea3852b6f6c43cbf1f2ceb25 Mon Sep 17 00:00:00 2001 From: Lipu Fei Date: Thu, 23 Nov 2017 14:07:38 +0100 Subject: [PATCH 02/24] Optimize MaterialsModel update CURA-4546 --- cura/Settings/MaterialsModel.py | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/cura/Settings/MaterialsModel.py b/cura/Settings/MaterialsModel.py index bee9307b53..bab8929765 100644 --- a/cura/Settings/MaterialsModel.py +++ b/cura/Settings/MaterialsModel.py @@ -18,4 +18,8 @@ class MaterialsModel(InstanceContainersModel): # \param container The container whose metadata was changed. def _onContainerMetaDataChanged(self, container): if container.getMetaDataEntry("type") == "material": #Only need to update if a material was changed. - self._update() \ No newline at end of file + self._update() + + def _onContainerChanged(self, container): + if container.getMetaDataEntry("type", "") == "material": + super()._onContainerChanged(container) From dad2dfda89e0c26b409f1bb4d981bacc1a8f0b39 Mon Sep 17 00:00:00 2001 From: Lipu Fei Date: Thu, 23 Nov 2017 14:08:10 +0100 Subject: [PATCH 03/24] No need to set currentItem after a material is imported CURA-4546 --- resources/qml/Preferences/MaterialsPage.qml | 1 - 1 file changed, 1 deletion(-) diff --git a/resources/qml/Preferences/MaterialsPage.qml b/resources/qml/Preferences/MaterialsPage.qml index 5e014faf24..cd04b79b20 100644 --- a/resources/qml/Preferences/MaterialsPage.qml +++ b/resources/qml/Preferences/MaterialsPage.qml @@ -322,7 +322,6 @@ UM.ManagementPage { messageDialog.icon = StandardIcon.Information messageDialog.text = catalog.i18nc("@info:status Don't translate the XML tag !", "Successfully imported material %1").arg(fileUrl) - currentItem = base.model.getItem(base.objectList.currentIndex) } else if(result.status == "duplicate") { From 033cc4fbc79cdaedd554805c2e7c12a56307363e Mon Sep 17 00:00:00 2001 From: Lipu Fei Date: Thu, 23 Nov 2017 14:12:23 +0100 Subject: [PATCH 04/24] Fix quality update in project loading CURA-4613 --- plugins/3MFReader/ThreeMFWorkspaceReader.py | 1 + 1 file changed, 1 insertion(+) diff --git a/plugins/3MFReader/ThreeMFWorkspaceReader.py b/plugins/3MFReader/ThreeMFWorkspaceReader.py index 65f026685b..d54e0a724e 100755 --- a/plugins/3MFReader/ThreeMFWorkspaceReader.py +++ b/plugins/3MFReader/ThreeMFWorkspaceReader.py @@ -799,6 +799,7 @@ class ThreeMFWorkspaceReader(WorkspaceReader): if quality.getId() not in ("empty", "empty_quality"): quality_type = quality.getMetaDataEntry("quality_type") quality_containers = self._container_registry.findInstanceContainers(definition = global_stack.definition.getId(), + type = "quality", quality_type = quality_type) if quality_containers: global_stack.quality = quality_containers[0] From e3cdcc04fd7fc20f0f478aa0e87ec8c50267cc02 Mon Sep 17 00:00:00 2001 From: Ghostkeeper Date: Thu, 23 Nov 2017 14:57:28 +0100 Subject: [PATCH 05/24] Document IRC channels --- README.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/README.md b/README.md index f8d809df16..ba6a986093 100644 --- a/README.md +++ b/README.md @@ -20,6 +20,8 @@ For crashes and similar issues, please attach the following information: If the Cura user interface still starts, you can also reach this directory from the application menu in Help -> Show settings folder +For additional support, you could also ask in the #cura channel on FreeNode IRC. For help with development, there is also the #cura-dev channel. + Dependencies ------------ From ef37f0d8c78bbbeee97737a61cbfe189808f96f9 Mon Sep 17 00:00:00 2001 From: Lipu Fei Date: Thu, 23 Nov 2017 15:34:51 +0100 Subject: [PATCH 06/24] Fix project loading to reset quality if it doesn't exist CURA-4617 --- plugins/3MFReader/ThreeMFWorkspaceReader.py | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/plugins/3MFReader/ThreeMFWorkspaceReader.py b/plugins/3MFReader/ThreeMFWorkspaceReader.py index d54e0a724e..ccdff869a0 100755 --- a/plugins/3MFReader/ThreeMFWorkspaceReader.py +++ b/plugins/3MFReader/ThreeMFWorkspaceReader.py @@ -803,6 +803,22 @@ class ThreeMFWorkspaceReader(WorkspaceReader): quality_type = quality_type) if quality_containers: global_stack.quality = quality_containers[0] + else: + # the quality_type of the quality profile cannot be found. + # this can happen if a quality_type has been removed in a newer version, for example: + # "extra_coarse" is removed from 2.7 to 3.0 + # in this case, the quality will be reset to "normal" + quality_containers = self._container_registry.findInstanceContainers( + definition = global_stack.definition.getId(), + type = "quality", + quality_type = "normal") + if quality_containers: + global_stack.quality = quality_containers[0] + else: + # This should not happen! + Logger.log("e", "Cannot find quality normal for global stack [%s] [%s]", + global_stack.getId(), global_stack.definition.getId()) + global_stack.quality = self._container_registry.findInstanceContainers(id = "empty_quality") # Replacing the old containers if resolve is "new". # When resolve is "new", some containers will get renamed, so all the other containers that reference to those From 2c6b2b869ef20686cf38395c20fe94d3eb4d8f06 Mon Sep 17 00:00:00 2001 From: Diego Prado Gesto Date: Thu, 23 Nov 2017 15:39:22 +0100 Subject: [PATCH 07/24] CURA-4605 Fix render issues when there are empty layers. Fix layer gap when raft is enabled. --- .../CuraEngineBackend/ProcessSlicedLayersJob.py | 16 ++++++++-------- plugins/SimulationView/SimulationView.py | 2 +- 2 files changed, 9 insertions(+), 9 deletions(-) diff --git a/plugins/CuraEngineBackend/ProcessSlicedLayersJob.py b/plugins/CuraEngineBackend/ProcessSlicedLayersJob.py index 51fcf3ec59..37ab451d16 100644 --- a/plugins/CuraEngineBackend/ProcessSlicedLayersJob.py +++ b/plugins/CuraEngineBackend/ProcessSlicedLayersJob.py @@ -95,22 +95,22 @@ class ProcessSlicedLayersJob(Job): # Find the minimum layer number # When using a raft, the raft layers are sent as layers < 0. Instead of allowing layers < 0, we - # instead simply offset all other layers so the lowest layer is always 0. + # instead simply offset all other layers so the lowest layer is always 0. It could happens that + # the first raft layer has value -8 but there are just 4 raft (negative) layers. min_layer_number = 0 + negative_layers = 0 for layer in self._layers: if layer.id < min_layer_number: min_layer_number = layer.id + if layer.id < 0: + negative_layers += 1 current_layer = 0 for layer in self._layers: - abs_layer_number = layer.id + abs(min_layer_number) - - # Workaround when the last layer doesn't have paths, this layer is skipped because this was generating - # some glitches when rendering. - if layer.id == len(self._layers)-1 and layer.repeatedMessageCount("path_segment") == 0: - Logger.log("i", "No sliced data in the layer", layer.id) - continue + # Negative layers are offset by the minimum layer number, but the positive layers are just + # offset by the number of negative layers so there is no layer gap between raft and model + abs_layer_number = layer.id + abs(min_layer_number) if layer.id < 0 else layer.id + negative_layers layer_data.addLayer(abs_layer_number) this_layer = layer_data.getLayer(abs_layer_number) diff --git a/plugins/SimulationView/SimulationView.py b/plugins/SimulationView/SimulationView.py index 2751ea4f60..b7bff91f9b 100644 --- a/plugins/SimulationView/SimulationView.py +++ b/plugins/SimulationView/SimulationView.py @@ -376,7 +376,7 @@ class SimulationView(View): if layer is None: return new_max_paths = layer.lineMeshElementCount() - if new_max_paths > 0 and new_max_paths != self._max_paths: + if new_max_paths >= 0 and new_max_paths != self._max_paths: self._max_paths = new_max_paths self.maxPathsChanged.emit() From 6b3e1303494e380fc2cbd9aaa8cf9d05a5a6e624 Mon Sep 17 00:00:00 2001 From: Lipu Fei Date: Thu, 23 Nov 2017 16:27:17 +0100 Subject: [PATCH 08/24] Fix edge cases with ultimaker2 and whatever other machines that may get affected CURA-4617 --- plugins/3MFReader/ThreeMFWorkspaceReader.py | 41 ++++++++++++++------- 1 file changed, 27 insertions(+), 14 deletions(-) diff --git a/plugins/3MFReader/ThreeMFWorkspaceReader.py b/plugins/3MFReader/ThreeMFWorkspaceReader.py index ccdff869a0..dfb16b91e1 100755 --- a/plugins/3MFReader/ThreeMFWorkspaceReader.py +++ b/plugins/3MFReader/ThreeMFWorkspaceReader.py @@ -751,12 +751,15 @@ class ThreeMFWorkspaceReader(WorkspaceReader): if stack.definitionChanges == self._container_registry.getEmptyInstanceContainer(): stack.setDefinitionChanges(CuraStackBuilder.createDefinitionChangesContainer(stack, stack.getId() + "_settings")) - extruder_stacks.append(stack) + if stack.getMetaDataEntry("type") == "extruder_train": + extruder_stacks.append(stack) # If not extruder stacks were saved in the project file (pre 3.1) create one manually # We re-use the container registry's addExtruderStackForSingleExtrusionMachine method for this if not extruder_stacks: - extruder_stacks.append(self._container_registry.addExtruderStackForSingleExtrusionMachine(global_stack, "fdmextruder")) + stack = self._container_registry.addExtruderStackForSingleExtrusionMachine(global_stack, "fdmextruder") + if stack: + extruder_stacks.append(stack) except: Logger.logException("w", "We failed to serialize the stack. Trying to clean up.") @@ -801,24 +804,34 @@ class ThreeMFWorkspaceReader(WorkspaceReader): quality_containers = self._container_registry.findInstanceContainers(definition = global_stack.definition.getId(), type = "quality", quality_type = quality_type) + quality_containers = [q for q in quality_containers if q.getMetaDataEntry("material", "") == ""] if quality_containers: global_stack.quality = quality_containers[0] else: - # the quality_type of the quality profile cannot be found. - # this can happen if a quality_type has been removed in a newer version, for example: - # "extra_coarse" is removed from 2.7 to 3.0 - # in this case, the quality will be reset to "normal" - quality_containers = self._container_registry.findInstanceContainers( - definition = global_stack.definition.getId(), - type = "quality", - quality_type = "normal") + # look for "fdmprinter" qualities if the machine-specific qualities cannot be found + quality_containers = self._container_registry.findInstanceContainers(definition = "fdmprinter", + type = "quality", + quality_type = quality_type) + quality_containers = [q for q in quality_containers if q.getMetaDataEntry("material", "") == ""] if quality_containers: global_stack.quality = quality_containers[0] else: - # This should not happen! - Logger.log("e", "Cannot find quality normal for global stack [%s] [%s]", - global_stack.getId(), global_stack.definition.getId()) - global_stack.quality = self._container_registry.findInstanceContainers(id = "empty_quality") + # the quality_type of the quality profile cannot be found. + # this can happen if a quality_type has been removed in a newer version, for example: + # "extra_coarse" is removed from 2.7 to 3.0 + # in this case, the quality will be reset to "normal" + quality_containers = self._container_registry.findInstanceContainers( + definition = global_stack.definition.getId(), + type = "quality", + quality_type = "normal") + quality_containers = [q for q in quality_containers if q.getMetaDataEntry("material", "") == ""] + if quality_containers: + global_stack.quality = quality_containers[0] + else: + # This should not happen! + Logger.log("e", "Cannot find quality normal for global stack [%s] [%s]", + global_stack.getId(), global_stack.definition.getId()) + global_stack.quality = self._container_registry.findInstanceContainers(id = "empty_quality")[0] # Replacing the old containers if resolve is "new". # When resolve is "new", some containers will get renamed, so all the other containers that reference to those From 7bb82cf56f702df6e3a36cf2ba1c2525709f355e Mon Sep 17 00:00:00 2001 From: Diego Prado Gesto Date: Thu, 23 Nov 2017 16:47:34 +0100 Subject: [PATCH 09/24] CURA-4605 Fix render issues when importing a GCode that has empty layers. Also fix gaps between raft and the model. --- plugins/GCodeReader/GCodeReader.py | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) diff --git a/plugins/GCodeReader/GCodeReader.py b/plugins/GCodeReader/GCodeReader.py index 2a7e29e370..d37769ec3a 100755 --- a/plugins/GCodeReader/GCodeReader.py +++ b/plugins/GCodeReader/GCodeReader.py @@ -143,6 +143,11 @@ class GCodeReader(MeshReader): this_layer.polygons.append(this_poly) return True + def _createEmptyLayer(self, layer_number): + self._layer_data_builder.addLayer(layer_number) + self._layer_data_builder.setLayerHeight(layer_number, 0) + self._layer_data_builder.setLayerThickness(layer_number, 0) + def _calculateLineWidth(self, current_point, previous_point, current_extrusion, previous_extrusion, layer_thickness): # Area of the filament Af = (self._filament_diameter / 2) ** 2 * numpy.pi @@ -322,6 +327,9 @@ class GCodeReader(MeshReader): current_position = self._position(0, 0, 0, 0, [0]) current_path = [] + min_layer_number = 0 + negative_layers = 0 + previous_layer = 0 for line in file: if self._cancelled: @@ -359,7 +367,23 @@ class GCodeReader(MeshReader): layer_number = int(line[len(self._layer_keyword):]) self._createPolygon(self._current_layer_thickness, current_path, self._extruder_offsets.get(self._extruder_number, [0, 0])) current_path.clear() + + # When using a raft, the raft layers are stored as layers < 0, it mimics the same behavior + # as in ProcessSlicedLayersJob + if layer_number < min_layer_number: + min_layer_number = layer_number + if layer_number < 0: + layer_number += abs(min_layer_number) + negative_layers += 1 + else: + layer_number += negative_layers + + # In case there is a gap in the layer count, empty layers are created + for empty_layer in range(previous_layer + 1, layer_number): + self._createEmptyLayer(empty_layer) + self._layer_number = layer_number + previous_layer = layer_number except: pass From c7667b56e240c0426d4f866e513af1055a7066da Mon Sep 17 00:00:00 2001 From: Lipu Fei Date: Fri, 24 Nov 2017 09:45:59 +0100 Subject: [PATCH 10/24] Multiple fixes for stacks CURA-4617 --- cura/Settings/CuraContainerRegistry.py | 6 ++---- cura/Settings/CuraContainerStack.py | 6 +++--- 2 files changed, 5 insertions(+), 7 deletions(-) diff --git a/cura/Settings/CuraContainerRegistry.py b/cura/Settings/CuraContainerRegistry.py index 543678ee22..3590d70602 100644 --- a/cura/Settings/CuraContainerRegistry.py +++ b/cura/Settings/CuraContainerRegistry.py @@ -454,16 +454,14 @@ class CuraContainerRegistry(ContainerRegistry): material_id = "default" if machine.material.getId() not in ("empty", "empty_material"): - # TODO: find the ID that's suitable for this extruder - pass + material_id = machine.material.getId() else: material_id = "empty_material" extruder_stack.setMaterialById(material_id) quality_id = "default" if machine.quality.getId() not in ("empty", "empty_quality"): - # TODO: find the ID that's suitable for this extruder - pass + quality_id = machine.quality.getId() else: quality_id = "empty_quality" extruder_stack.setQualityById(quality_id) diff --git a/cura/Settings/CuraContainerStack.py b/cura/Settings/CuraContainerStack.py index 156883ade3..f0cec3c450 100755 --- a/cura/Settings/CuraContainerStack.py +++ b/cura/Settings/CuraContainerStack.py @@ -121,7 +121,7 @@ class CuraContainerStack(ContainerStack): # # \throws Exceptions.InvalidContainerError Raised when no container could be found with the specified ID. def setQualityById(self, new_quality_id: str) -> None: - quality = self._empty_instance_container + quality = self._empty_quality if new_quality_id == "default": new_quality = self.findDefaultQuality() if new_quality: @@ -159,7 +159,7 @@ class CuraContainerStack(ContainerStack): # # \throws Exceptions.InvalidContainerError Raised when no container could be found with the specified ID. def setMaterialById(self, new_material_id: str) -> None: - material = self._empty_instance_container + material = self._empty_material if new_material_id == "default": new_material = self.findDefaultMaterial() if new_material: @@ -197,7 +197,7 @@ class CuraContainerStack(ContainerStack): # # \throws Exceptions.InvalidContainerError Raised when no container could be found with the specified ID. def setVariantById(self, new_variant_id: str) -> None: - variant = self._empty_instance_container + variant = self._empty_variant if new_variant_id == "default": new_variant = self.findDefaultVariant() if new_variant: From 0b434978dd7585782dbefd16f89058cabc5b382a Mon Sep 17 00:00:00 2001 From: Diego Prado Gesto Date: Fri, 24 Nov 2017 10:34:38 +0100 Subject: [PATCH 11/24] CURA-4561 Add tooltip also to the Cancel button. --- resources/qml/SaveButton.qml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/resources/qml/SaveButton.qml b/resources/qml/SaveButton.qml index 3237dd9ade..b258ecad43 100644 --- a/resources/qml/SaveButton.qml +++ b/resources/qml/SaveButton.qml @@ -157,7 +157,7 @@ Item { Button { id: prepareButton - tooltip: catalog.i18nc("@info:tooltip","Slice"); + tooltip: [1, 5].indexOf(UM.Backend.state) != -1 ? catalog.i18nc("@info:tooltip","Slice current printjob") : catalog.i18nc("@info:tooltip","Cancel slicing process") // 1 = not started, 2 = Processing enabled: (base.backendState == 1 || base.backendState == 2) && base.activity == true visible: { From 9ecfd5510a6f5e97645e061eaeaa84e5395dd49e Mon Sep 17 00:00:00 2001 From: Ghostkeeper Date: Fri, 24 Nov 2017 10:42:09 +0100 Subject: [PATCH 12/24] Clarify description for when bed temperature is 0 Fixes #2674. --- resources/definitions/fdmprinter.def.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/resources/definitions/fdmprinter.def.json b/resources/definitions/fdmprinter.def.json index 88ec34274e..0d0bc9dea1 100644 --- a/resources/definitions/fdmprinter.def.json +++ b/resources/definitions/fdmprinter.def.json @@ -1966,7 +1966,7 @@ "material_bed_temperature": { "label": "Build Plate Temperature", - "description": "The temperature used for the heated build plate. If this is 0, the bed will not heat up for this print.", + "description": "The temperature used for the heated build plate. If this is 0, the bed temperature will not be adjusted.", "unit": "°C", "type": "float", "resolve": "max(extruderValues('material_bed_temperature'))", From c8c2129b7e7e2174181aed923994f1d6b6371eaf Mon Sep 17 00:00:00 2001 From: Diego Prado Gesto Date: Fri, 24 Nov 2017 10:51:34 +0100 Subject: [PATCH 13/24] CURA-4552 Minor changes --- plugins/GCodeReader/GCodeReader.py | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/plugins/GCodeReader/GCodeReader.py b/plugins/GCodeReader/GCodeReader.py index 6578163aaf..14d3a2b741 100755 --- a/plugins/GCodeReader/GCodeReader.py +++ b/plugins/GCodeReader/GCodeReader.py @@ -211,7 +211,6 @@ class GCodeReader(MeshReader): return self._position( params.x if params.x is not None else position.x, params.y if params.y is not None else position.y, - 0, position.f, position.e) @@ -274,11 +273,11 @@ class GCodeReader(MeshReader): position.e.extend([0] * (self._extruder_number - len(position.e) + 1)) return position - def _processMCode(self, m): - if m == 82: + def _processMCode(self, M): + if M == 82: # Set absolute extrusion mode self._is_absolute_extrusion = True - elif m == 83: + elif M == 83: # Set relative extrusion mode self._is_absolute_extrusion = False From bf1ecba641a0c6cc702a4b72474976d5ac217196 Mon Sep 17 00:00:00 2001 From: Diego Prado Gesto Date: Fri, 24 Nov 2017 10:54:20 +0100 Subject: [PATCH 14/24] Add the layer thickness back to the color options in Simulation View --- plugins/SimulationView/SimulationView.qml | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/plugins/SimulationView/SimulationView.qml b/plugins/SimulationView/SimulationView.qml index bc224f19e2..42cd23cd5f 100644 --- a/plugins/SimulationView/SimulationView.qml +++ b/plugins/SimulationView/SimulationView.qml @@ -138,11 +138,10 @@ Item text: catalog.i18nc("@label:listbox", "Feedrate"), type_id: 2 }) - // TODO DON'T DELETE!!!! This part must be enabled when adaptive layer height feature is available -// layerViewTypes.append({ -// text: catalog.i18nc("@label:listbox", "Layer thickness"), -// type_id: 3 // these ids match the switching in the shader -// }) + layerViewTypes.append({ + text: catalog.i18nc("@label:listbox", "Layer thickness"), + type_id: 3 // these ids match the switching in the shader + }) } ComboBox From 6cea9c59e89658e4d68c76a12e0a071486de0dc2 Mon Sep 17 00:00:00 2001 From: Aleksei S Date: Fri, 24 Nov 2017 11:59:09 +0100 Subject: [PATCH 15/24] Prevent crash handler exception --- cura/CrashHandler.py | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/cura/CrashHandler.py b/cura/CrashHandler.py index c6f94f0a80..fc12bff620 100644 --- a/cura/CrashHandler.py +++ b/cura/CrashHandler.py @@ -280,5 +280,7 @@ class CrashHandler: Application.getInstance().callLater(self._show) def _show(self): - self.dialog.exec_() - os._exit(1) + # When the exception is not in the fatal_exception_types list, the dialog is not created, so we don't need to show it + if self.dialog: + self.dialog.exec_() + os._exit(1) From 1ea937991343720c1fe0f32e942c21bdf94f8bc8 Mon Sep 17 00:00:00 2001 From: Diego Prado Gesto Date: Fri, 24 Nov 2017 13:02:11 +0100 Subject: [PATCH 16/24] CURA-4609 Fix qml rectangle background in feedrate color scheme. --- plugins/SimulationView/SimulationView.qml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/SimulationView/SimulationView.qml b/plugins/SimulationView/SimulationView.qml index 17c71d2733..d802335304 100644 --- a/plugins/SimulationView/SimulationView.qml +++ b/plugins/SimulationView/SimulationView.qml @@ -349,7 +349,7 @@ Item } // Text for the minimum, maximum and units for the feedrates and layer thickness - Rectangle { + Item { id: gradientLegend visible: view_settings.show_gradient width: parent.width From 147cbdf592d010bcb42db72e00bfccf3b504e0d5 Mon Sep 17 00:00:00 2001 From: Ghostkeeper Date: Fri, 24 Nov 2017 12:43:41 +0100 Subject: [PATCH 17/24] Clarify translations of 'unknown' For some languages, the gender matters. Contributes to issue CURA-4601. --- plugins/UM3NetworkPrinting/DiscoverUM3Action.qml | 6 +++--- .../UM3NetworkPrinting/NetworkClusterPrinterOutputDevice.py | 2 +- plugins/UM3NetworkPrinting/PrinterInfoBlock.qml | 2 +- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/plugins/UM3NetworkPrinting/DiscoverUM3Action.qml b/plugins/UM3NetworkPrinting/DiscoverUM3Action.qml index cec2bf0f0f..cb574384f9 100644 --- a/plugins/UM3NetworkPrinting/DiscoverUM3Action.qml +++ b/plugins/UM3NetworkPrinting/DiscoverUM3Action.qml @@ -230,13 +230,13 @@ Cura.MachineAction { if(base.selectedPrinter.printerType == "ultimaker3") { - return catalog.i18nc("@label", "Ultimaker 3") + return catalog.i18nc("@label Printer name", "Ultimaker 3") } else if(base.selectedPrinter.printerType == "ultimaker3_extended") { - return catalog.i18nc("@label", "Ultimaker 3 Extended") + return catalog.i18nc("@label Printer name", "Ultimaker 3 Extended") } else { - return catalog.i18nc("@label", "Unknown") // We have no idea what type it is. Should not happen 'in the field' + return catalog.i18nc("@label Printer name", "Unknown") // We have no idea what type it is. Should not happen 'in the field' } } else diff --git a/plugins/UM3NetworkPrinting/NetworkClusterPrinterOutputDevice.py b/plugins/UM3NetworkPrinting/NetworkClusterPrinterOutputDevice.py index b6e94121f8..09518575c9 100644 --- a/plugins/UM3NetworkPrinting/NetworkClusterPrinterOutputDevice.py +++ b/plugins/UM3NetworkPrinting/NetworkClusterPrinterOutputDevice.py @@ -486,7 +486,7 @@ class NetworkClusterPrinterOutputDevice(NetworkPrinterOutputDevice.NetworkPrinte printer_name = self.__getPrinterNameFromUuid(print_job["printer_uuid"]) if printer_name is None: - printer_name = i18n_catalog.i18nc("@label", "Unknown") + printer_name = i18n_catalog.i18nc("@label Printer name", "Unknown") message_text = (i18n_catalog.i18nc("@info:status", "Printer '{printer_name}' has finished printing '{job_name}'.") diff --git a/plugins/UM3NetworkPrinting/PrinterInfoBlock.qml b/plugins/UM3NetworkPrinting/PrinterInfoBlock.qml index 7ae8520d19..c253ebae89 100644 --- a/plugins/UM3NetworkPrinting/PrinterInfoBlock.qml +++ b/plugins/UM3NetworkPrinting/PrinterInfoBlock.qml @@ -44,7 +44,7 @@ Rectangle case "maintenance": // TODO: new string case "unknown": default: - return catalog.i18nc("@label", "Unknown"); + return catalog.i18nc("@label Printer status", "Unknown"); } } From 4a8dacbe063188995b122f789a8750aa202f19cf Mon Sep 17 00:00:00 2001 From: Ghostkeeper Date: Fri, 24 Nov 2017 13:11:05 +0100 Subject: [PATCH 18/24] Make crash handler easier to translate All that formatting doesn't need to be translated along. It's only confusing, especially because of those variable names. They always need to be in that position anyway. Contributes to issue CURA-4601. --- cura/CrashHandler.py | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/cura/CrashHandler.py b/cura/CrashHandler.py index fc12bff620..7a386ee903 100644 --- a/cura/CrashHandler.py +++ b/cura/CrashHandler.py @@ -108,11 +108,11 @@ class CrashHandler: except: self.cura_version = catalog.i18nc("@label unknown version of Cura", "Unknown") - crash_info = catalog.i18nc("@label Cura version", "Cura version: {version}
").format(version = self.cura_version) - crash_info += catalog.i18nc("@label Platform", "Platform: {platform}
").format(platform = platform.platform()) - crash_info += catalog.i18nc("@label Qt version", "Qt version: {qt}
").format(qt = QT_VERSION_STR) - crash_info += catalog.i18nc("@label PyQt version", "PyQt version: {pyqt}
").format(pyqt = PYQT_VERSION_STR) - crash_info += catalog.i18nc("@label OpenGL", "OpenGL: {opengl}
").format(opengl = self._getOpenGLInfo()) + crash_info = "" + catalog.i18nc("@label Cura version number", "Cura version") + ": " + str(self.cura_version) + "
" + crash_info += "" + catalog.i18nc("@label Type of platform", "Platform") + ": " + str(platform.platform()) + "
" + crash_info += "" + catalog.i18nc("@label", "Qt version") + ": " + str(QT_VERSION_STR) + "
" + crash_info += "" + catalog.i18nc("@label", "PyQt version") + ": " + str(PYQT_VERSION_STR) + "
" + crash_info += "" + catalog.i18nc("@label OpenGL version", "OpenGL") + ": " + str(self._getOpenGLInfo()) + "
" label.setText(crash_info) layout.addWidget(label) From a0ae7489f8013b87763fa4b11a0e831b6f346e60 Mon Sep 17 00:00:00 2001 From: Ghostkeeper Date: Fri, 24 Nov 2017 13:15:43 +0100 Subject: [PATCH 19/24] Less technical term for X/Y offset of infill Just in the description. It's good to describe a setting using different words than the setting name. Contributes to issue CURA-4601. --- resources/definitions/fdmprinter.def.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/resources/definitions/fdmprinter.def.json b/resources/definitions/fdmprinter.def.json index 0d0bc9dea1..8db02b67f8 100644 --- a/resources/definitions/fdmprinter.def.json +++ b/resources/definitions/fdmprinter.def.json @@ -1568,7 +1568,7 @@ "infill_offset_x": { "label": "Infill X Offset", - "description": "The infill pattern is offset this distance along the X axis.", + "description": "The infill pattern is moved this distance along the X axis.", "unit": "mm", "type": "float", "default_value": 0, @@ -1579,7 +1579,7 @@ "infill_offset_y": { "label": "Infill Y Offset", - "description": "The infill pattern is offset this distance along the Y axis.", + "description": "The infill pattern is moved this distance along the Y axis.", "unit": "mm", "type": "float", "default_value": 0, From d0c1569da6f323d5f8df4e8641a82a392840d176 Mon Sep 17 00:00:00 2001 From: Diego Prado Gesto Date: Wed, 22 Nov 2017 10:19:50 +0100 Subject: [PATCH 20/24] Merge branch 'fieldOfView-feature_simulation_ux_tweaks' --- plugins/SimulationView/SimulationView.qml | 328 ++++++++++++---------- resources/themes/cura-light/theme.json | 8 +- 2 files changed, 183 insertions(+), 153 deletions(-) diff --git a/plugins/SimulationView/SimulationView.qml b/plugins/SimulationView/SimulationView.qml index d802335304..bc224f19e2 100644 --- a/plugins/SimulationView/SimulationView.qml +++ b/plugins/SimulationView/SimulationView.qml @@ -20,7 +20,12 @@ Item } } height: { - if (UM.SimulationView.compatibilityMode) { + if (viewSettings.collapsed) { + if (UM.SimulationView.compatibilityMode) { + return UM.Theme.getSize("layerview_menu_size_compatibility_collapsed").height; + } + return UM.Theme.getSize("layerview_menu_size_collapsed").height; + } else if (UM.SimulationView.compatibilityMode) { return UM.Theme.getSize("layerview_menu_size_compatibility").height; } else if (UM.Preferences.getValue("layerview/layer_view_type") == 0) { return UM.Theme.getSize("layerview_menu_size_material_color_mode").height + UM.SimulationView.extruderCount * (UM.Theme.getSize("layerview_row").height + UM.Theme.getSize("layerview_row_spacing").height) @@ -28,6 +33,7 @@ Item return UM.Theme.getSize("layerview_menu_size").height + UM.SimulationView.extruderCount * (UM.Theme.getSize("layerview_row").height + UM.Theme.getSize("layerview_row_spacing").height) } } + Behavior on height { NumberAnimation { duration: 100 } } property var buttonTarget: { if(parent != null) @@ -40,21 +46,49 @@ Item visible: parent != null ? !parent.parent.monitoringPrint: true - UM.PointingRectangle { + Rectangle { id: layerViewMenu anchors.right: parent.right anchors.top: parent.top width: parent.width height: parent.height + clip: true z: layerSlider.z - 1 color: UM.Theme.getColor("tool_panel_background") - borderWidth: UM.Theme.getSize("default_lining").width - borderColor: UM.Theme.getColor("lining") - arrowSize: 0 // hide arrow until weird issue with first time rendering is fixed + border.width: UM.Theme.getSize("default_lining").width + border.color: UM.Theme.getColor("lining") + + Button { + id: collapseButton + anchors.top: parent.top + anchors.topMargin: Math.floor(UM.Theme.getSize("default_margin").height + (UM.Theme.getSize("layerview_row").height - UM.Theme.getSize("default_margin").height) / 2) + anchors.right: parent.right + anchors.rightMargin: UM.Theme.getSize("default_margin").width + + width: UM.Theme.getSize("standard_arrow").width + height: UM.Theme.getSize("standard_arrow").height + + onClicked: viewSettings.collapsed = !viewSettings.collapsed + + style: ButtonStyle + { + background: UM.RecolorImage + { + width: control.width + height: control.height + sourceSize.width: width + sourceSize.height: width + color: UM.Theme.getColor("setting_control_text") + source: viewSettings.collapsed ? UM.Theme.getIcon("arrow_left") : UM.Theme.getIcon("arrow_bottom") + } + label: Label{ } + } + } ColumnLayout { - id: view_settings + id: viewSettings + property bool collapsed: false property var extruder_opacities: UM.Preferences.getValue("layerview/extruder_opacities").split("|") property bool show_travel_moves: UM.Preferences.getValue("layerview/show_travel_moves") property bool show_helpers: UM.Preferences.getValue("layerview/show_helpers") @@ -70,9 +104,9 @@ Item anchors.topMargin: UM.Theme.getSize("default_margin").height anchors.left: parent.left anchors.leftMargin: UM.Theme.getSize("default_margin").width - spacing: UM.Theme.getSize("layerview_row_spacing").height anchors.right: parent.right anchors.rightMargin: UM.Theme.getSize("default_margin").width + spacing: UM.Theme.getSize("layerview_row_spacing").height Label { @@ -121,7 +155,6 @@ Item visible: !UM.SimulationView.compatibilityMode style: UM.Theme.styles.combobox anchors.right: parent.right - anchors.rightMargin: 10 * screenScaleFactor onActivated: { @@ -137,7 +170,7 @@ Item function updateLegends(type_id) { // update visibility of legends - view_settings.show_legend = UM.SimulationView.compatibilityMode || (type_id == 1); + viewSettings.show_legend = UM.SimulationView.compatibilityMode || (type_id == 1); } } @@ -155,12 +188,10 @@ Item Layout.preferredWidth: UM.Theme.getSize("layerview_row").width } - Label + Item { - id: space2Label - anchors.left: parent.left - text: " " - font.pointSize: 0.5 + height: Math.floor(UM.Theme.getSize("default_margin").width / 2) + width: width } Connections { @@ -170,13 +201,13 @@ Item layerTypeCombobox.currentIndex = UM.SimulationView.compatibilityMode ? 1 : UM.Preferences.getValue("layerview/layer_view_type"); layerTypeCombobox.updateLegends(layerTypeCombobox.currentIndex); playButton.pauseSimulation(); - view_settings.extruder_opacities = UM.Preferences.getValue("layerview/extruder_opacities").split("|"); - view_settings.show_travel_moves = UM.Preferences.getValue("layerview/show_travel_moves"); - view_settings.show_helpers = UM.Preferences.getValue("layerview/show_helpers"); - view_settings.show_skin = UM.Preferences.getValue("layerview/show_skin"); - view_settings.show_infill = UM.Preferences.getValue("layerview/show_infill"); - view_settings.only_show_top_layers = UM.Preferences.getValue("view/only_show_top_layers"); - view_settings.top_layer_count = UM.Preferences.getValue("view/top_layer_count"); + viewSettings.extruder_opacities = UM.Preferences.getValue("layerview/extruder_opacities").split("|"); + viewSettings.show_travel_moves = UM.Preferences.getValue("layerview/show_travel_moves"); + viewSettings.show_helpers = UM.Preferences.getValue("layerview/show_helpers"); + viewSettings.show_skin = UM.Preferences.getValue("layerview/show_skin"); + viewSettings.show_infill = UM.Preferences.getValue("layerview/show_infill"); + viewSettings.only_show_top_layers = UM.Preferences.getValue("view/only_show_top_layers"); + viewSettings.top_layer_count = UM.Preferences.getValue("view/top_layer_count"); } } @@ -184,24 +215,23 @@ Item model: Cura.ExtrudersModel{} CheckBox { id: extrudersModelCheckBox - checked: view_settings.extruder_opacities[index] > 0.5 || view_settings.extruder_opacities[index] == undefined || view_settings.extruder_opacities[index] == "" + checked: viewSettings.extruder_opacities[index] > 0.5 || viewSettings.extruder_opacities[index] == undefined || viewSettings.extruder_opacities[index] == "" onClicked: { - view_settings.extruder_opacities[index] = checked ? 1.0 : 0.0 - UM.Preferences.setValue("layerview/extruder_opacities", view_settings.extruder_opacities.join("|")); + viewSettings.extruder_opacities[index] = checked ? 1.0 : 0.0 + UM.Preferences.setValue("layerview/extruder_opacities", viewSettings.extruder_opacities.join("|")); } visible: !UM.SimulationView.compatibilityMode enabled: index + 1 <= 4 Rectangle { anchors.verticalCenter: parent.verticalCenter anchors.right: extrudersModelCheckBox.right - anchors.rightMargin: UM.Theme.getSize("default_margin").width width: UM.Theme.getSize("layerview_legend_size").width height: UM.Theme.getSize("layerview_legend_size").height color: model.color radius: width / 2 border.width: UM.Theme.getSize("default_lining").width border.color: UM.Theme.getColor("lining") - visible: !view_settings.show_legend & !view_settings.show_gradient + visible: !viewSettings.show_legend & !viewSettings.show_gradient } Layout.fillWidth: true Layout.preferredHeight: UM.Theme.getSize("layerview_row").height + UM.Theme.getSize("default_lining").height @@ -229,25 +259,25 @@ Item { typesLegendModel.append({ label: catalog.i18nc("@label", "Show Travels"), - initialValue: view_settings.show_travel_moves, + initialValue: viewSettings.show_travel_moves, preference: "layerview/show_travel_moves", colorId: "layerview_move_combing" }); typesLegendModel.append({ label: catalog.i18nc("@label", "Show Helpers"), - initialValue: view_settings.show_helpers, + initialValue: viewSettings.show_helpers, preference: "layerview/show_helpers", colorId: "layerview_support" }); typesLegendModel.append({ label: catalog.i18nc("@label", "Show Shell"), - initialValue: view_settings.show_skin, + initialValue: viewSettings.show_skin, preference: "layerview/show_skin", colorId: "layerview_inset_0" }); typesLegendModel.append({ label: catalog.i18nc("@label", "Show Infill"), - initialValue: view_settings.show_infill, + initialValue: viewSettings.show_infill, preference: "layerview/show_infill", colorId: "layerview_infill" }); @@ -263,13 +293,12 @@ Item Rectangle { anchors.verticalCenter: parent.verticalCenter anchors.right: legendModelCheckBox.right - anchors.rightMargin: UM.Theme.getSize("default_margin").width width: UM.Theme.getSize("layerview_legend_size").width height: UM.Theme.getSize("layerview_legend_size").height color: UM.Theme.getColor(model.colorId) border.width: UM.Theme.getSize("default_lining").width border.color: UM.Theme.getColor("lining") - visible: view_settings.show_legend + visible: viewSettings.show_legend } Layout.fillWidth: true Layout.preferredHeight: UM.Theme.getSize("layerview_row").height + UM.Theme.getSize("default_lining").height @@ -291,7 +320,7 @@ Item } CheckBox { - checked: view_settings.only_show_top_layers + checked: viewSettings.only_show_top_layers onClicked: { UM.Preferences.setValue("view/only_show_top_layers", checked ? 1.0 : 0.0); } @@ -300,7 +329,7 @@ Item style: UM.Theme.styles.checkbox } CheckBox { - checked: view_settings.top_layer_count == 5 + checked: viewSettings.top_layer_count == 5 onClicked: { UM.Preferences.setValue("view/top_layer_count", checked ? 5 : 1); } @@ -327,18 +356,17 @@ Item Label { text: label - visible: view_settings.show_legend + visible: viewSettings.show_legend id: typesLegendModelLabel Rectangle { anchors.verticalCenter: parent.verticalCenter anchors.right: typesLegendModelLabel.right - anchors.rightMargin: UM.Theme.getSize("default_margin").width width: UM.Theme.getSize("layerview_legend_size").width height: UM.Theme.getSize("layerview_legend_size").height color: UM.Theme.getColor(model.colorId) border.width: UM.Theme.getSize("default_lining").width border.color: UM.Theme.getColor("lining") - visible: view_settings.show_legend + visible: viewSettings.show_legend } Layout.fillWidth: true Layout.preferredHeight: UM.Theme.getSize("layerview_row").height + UM.Theme.getSize("default_lining").height @@ -351,7 +379,7 @@ Item // Text for the minimum, maximum and units for the feedrates and layer thickness Item { id: gradientLegend - visible: view_settings.show_gradient + visible: viewSettings.show_gradient width: parent.width height: UM.Theme.getSize("layerview_row").height anchors { @@ -427,7 +455,7 @@ Item Rectangle { // In QML 5.9 can be changed by LinearGradient // Invert values because then the bar is rotated 90 degrees id: gradient - visible: view_settings.show_gradient + visible: viewSettings.show_gradient anchors.left: parent.right height: parent.width width: UM.Theme.getSize("layerview_row").height * 1.5 @@ -458,134 +486,134 @@ Item } } } + } - Item { - id: slidersBox + Item { + id: slidersBox - width: parent.width - visible: UM.SimulationView.layerActivity && CuraApplication.platformActivity + width: parent.width + visible: UM.SimulationView.layerActivity && CuraApplication.platformActivity + + anchors { + top: parent.bottom + topMargin: UM.Theme.getSize("slider_layerview_margin").height + left: parent.left + } + + PathSlider { + id: pathSlider + + height: UM.Theme.getSize("slider_handle").width + anchors.right: playButton.left + anchors.rightMargin: UM.Theme.getSize("default_margin").width + anchors.left: parent.left + visible: !UM.SimulationView.compatibilityMode + + // custom properties + handleValue: UM.SimulationView.currentPath + maximumValue: UM.SimulationView.numPaths + handleSize: UM.Theme.getSize("slider_handle").width + trackThickness: UM.Theme.getSize("slider_groove").width + trackColor: UM.Theme.getColor("slider_groove") + trackBorderColor: UM.Theme.getColor("slider_groove_border") + handleColor: UM.Theme.getColor("slider_handle") + handleActiveColor: UM.Theme.getColor("slider_handle_active") + rangeColor: UM.Theme.getColor("slider_groove_fill") + + // update values when layer data changes + Connections { + target: UM.SimulationView + onMaxPathsChanged: pathSlider.setHandleValue(UM.SimulationView.currentPath) + onCurrentPathChanged: pathSlider.setHandleValue(UM.SimulationView.currentPath) + } + + // make sure the slider handlers show the correct value after switching views + Component.onCompleted: { + pathSlider.setHandleValue(UM.SimulationView.currentPath) + } + } + + LayerSlider { + id: layerSlider + + width: UM.Theme.getSize("slider_handle").width + height: UM.Theme.getSize("layerview_menu_size").height anchors { - top: parent.bottom - topMargin: UM.Theme.getSize("slider_layerview_margin").height - left: parent.left + top: !UM.SimulationView.compatibilityMode ? playButton.bottom : parent.top + topMargin: !UM.SimulationView.compatibilityMode ? UM.Theme.getSize("default_margin").height : 0 + right: parent.right + rightMargin: UM.Theme.getSize("slider_layerview_margin").width } - PathSlider { - id: pathSlider + // custom properties + upperValue: UM.SimulationView.currentLayer + lowerValue: UM.SimulationView.minimumLayer + maximumValue: UM.SimulationView.numLayers + handleSize: UM.Theme.getSize("slider_handle").width + trackThickness: UM.Theme.getSize("slider_groove").width + trackColor: UM.Theme.getColor("slider_groove") + trackBorderColor: UM.Theme.getColor("slider_groove_border") + upperHandleColor: UM.Theme.getColor("slider_handle") + lowerHandleColor: UM.Theme.getColor("slider_handle") + rangeHandleColor: UM.Theme.getColor("slider_groove_fill") + handleActiveColor: UM.Theme.getColor("slider_handle_active") + handleLabelWidth: UM.Theme.getSize("slider_layerview_background").width - width: parent.width - height: UM.Theme.getSize("slider_handle").width - anchors.left: parent.left - visible: !UM.SimulationView.compatibilityMode - - // custom properties - handleValue: UM.SimulationView.currentPath - maximumValue: UM.SimulationView.numPaths - handleSize: UM.Theme.getSize("slider_handle").width - trackThickness: UM.Theme.getSize("slider_groove").width - trackColor: UM.Theme.getColor("slider_groove") - trackBorderColor: UM.Theme.getColor("slider_groove_border") - handleColor: UM.Theme.getColor("slider_handle") - handleActiveColor: UM.Theme.getColor("slider_handle_active") - rangeColor: UM.Theme.getColor("slider_groove_fill") - - // update values when layer data changes - Connections { - target: UM.SimulationView - onMaxPathsChanged: pathSlider.setHandleValue(UM.SimulationView.currentPath) - onCurrentPathChanged: pathSlider.setHandleValue(UM.SimulationView.currentPath) - } - - // make sure the slider handlers show the correct value after switching views - Component.onCompleted: { - pathSlider.setHandleValue(UM.SimulationView.currentPath) - } + // update values when layer data changes + Connections { + target: UM.SimulationView + onMaxLayersChanged: layerSlider.setUpperValue(UM.SimulationView.currentLayer) + onMinimumLayerChanged: layerSlider.setLowerValue(UM.SimulationView.minimumLayer) + onCurrentLayerChanged: layerSlider.setUpperValue(UM.SimulationView.currentLayer) } - LayerSlider { - id: layerSlider + // make sure the slider handlers show the correct value after switching views + Component.onCompleted: { + layerSlider.setLowerValue(UM.SimulationView.minimumLayer) + layerSlider.setUpperValue(UM.SimulationView.currentLayer) + } + } - width: UM.Theme.getSize("slider_handle").width - height: UM.Theme.getSize("layerview_menu_size").height - - anchors { - top: pathSlider.bottom - topMargin: UM.Theme.getSize("slider_layerview_margin").height - right: parent.right - rightMargin: UM.Theme.getSize("slider_layerview_margin").width - } - - // custom properties - upperValue: UM.SimulationView.currentLayer - lowerValue: UM.SimulationView.minimumLayer - maximumValue: UM.SimulationView.numLayers - handleSize: UM.Theme.getSize("slider_handle").width - trackThickness: UM.Theme.getSize("slider_groove").width - trackColor: UM.Theme.getColor("slider_groove") - trackBorderColor: UM.Theme.getColor("slider_groove_border") - upperHandleColor: UM.Theme.getColor("slider_handle") - lowerHandleColor: UM.Theme.getColor("slider_handle") - rangeHandleColor: UM.Theme.getColor("slider_groove_fill") - handleActiveColor: UM.Theme.getColor("slider_handle_active") - handleLabelWidth: UM.Theme.getSize("slider_layerview_background").width - - // update values when layer data changes - Connections { - target: UM.SimulationView - onMaxLayersChanged: layerSlider.setUpperValue(UM.SimulationView.currentLayer) - onMinimumLayerChanged: layerSlider.setLowerValue(UM.SimulationView.minimumLayer) - onCurrentLayerChanged: layerSlider.setUpperValue(UM.SimulationView.currentLayer) - } - - // make sure the slider handlers show the correct value after switching views - Component.onCompleted: { - layerSlider.setLowerValue(UM.SimulationView.minimumLayer) - layerSlider.setUpperValue(UM.SimulationView.currentLayer) - } + // Play simulation button + Button { + id: playButton + implicitWidth: Math.floor(UM.Theme.getSize("button").width * 0.75) + implicitHeight: Math.floor(UM.Theme.getSize("button").height * 0.75) + iconSource: "./resources/simulation_resume.svg" + style: UM.Theme.styles.tool_button + visible: !UM.SimulationView.compatibilityMode + anchors { + horizontalCenter: layerSlider.horizontalCenter + verticalCenter: pathSlider.verticalCenter } - // Play simulation button - Button { - id: playButton - implicitWidth: UM.Theme.getSize("button").width * 0.75; - implicitHeight: UM.Theme.getSize("button").height * 0.75; - iconSource: "./resources/simulation_resume.svg" - style: UM.Theme.styles.tool_button - visible: !UM.SimulationView.compatibilityMode - anchors { - horizontalCenter: layerSlider.horizontalCenter - top: layerSlider.bottom - topMargin: UM.Theme.getSize("slider_layerview_margin").width - } + property var status: 0 // indicates if it's stopped (0) or playing (1) - property var status: 0 // indicates if it's stopped (0) or playing (1) - - onClicked: { - switch(status) { - case 0: { - resumeSimulation() - break - } - case 1: { - pauseSimulation() - break - } + onClicked: { + switch(status) { + case 0: { + resumeSimulation() + break + } + case 1: { + pauseSimulation() + break } } + } - function pauseSimulation() { - UM.SimulationView.setSimulationRunning(false) - iconSource = "./resources/simulation_resume.svg" - simulationTimer.stop() - status = 0 - } + function pauseSimulation() { + UM.SimulationView.setSimulationRunning(false) + iconSource = "./resources/simulation_resume.svg" + simulationTimer.stop() + status = 0 + } - function resumeSimulation() { - UM.SimulationView.setSimulationRunning(true) - iconSource = "./resources/simulation_pause.svg" - simulationTimer.start() - } + function resumeSimulation() { + UM.SimulationView.setSimulationRunning(true) + iconSource = "./resources/simulation_pause.svg" + simulationTimer.start() } } diff --git a/resources/themes/cura-light/theme.json b/resources/themes/cura-light/theme.json index 4197285dd8..09f93d413e 100644 --- a/resources/themes/cura-light/theme.json +++ b/resources/themes/cura-light/theme.json @@ -344,11 +344,13 @@ "slider_handle": [1.0, 1.0], "slider_layerview_size": [1.0, 22.0], "slider_layerview_background": [4.0, 0.0], - "slider_layerview_margin": [1.0, 1.0], + "slider_layerview_margin": [1.0, 1.5], - "layerview_menu_size": [15, 19.5], - "layerview_menu_size_material_color_mode": [15, 15.5], + "layerview_menu_size": [15, 20], + "layerview_menu_size_material_color_mode": [15, 16], + "layerview_menu_size_collapsed": [15, 6], "layerview_menu_size_compatibility": [22, 22.0], + "layerview_menu_size_compatibility_collapsed": [15, 3.5], "layerview_legend_size": [1.0, 1.0], "layerview_row": [11.0, 1.5], "layerview_row_spacing": [0.0, 0.5], From bb2be70daccab8110864ff3b3677687e01124be8 Mon Sep 17 00:00:00 2001 From: Aleksei S Date: Sat, 25 Nov 2017 02:25:36 +0100 Subject: [PATCH 21/24] Finds candidate quality profile for fdmextruder CURA-4620 --- cura/Settings/MachineManager.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/cura/Settings/MachineManager.py b/cura/Settings/MachineManager.py index ca929b46fc..6b03916fdf 100755 --- a/cura/Settings/MachineManager.py +++ b/cura/Settings/MachineManager.py @@ -769,9 +769,10 @@ class MachineManager(QObject): candidate_quality = None if quality_type: candidate_quality = quality_manager.findQualityByQualityType(quality_type, - quality_manager.getWholeMachineDefinition(machine_definition), + quality_manager.getWholeMachineDefinition(material_container.getDefinition()), [material_container]) + if not candidate_quality or isinstance(candidate_quality, type(self._empty_quality_changes_container)): Logger.log("d", "Attempting to find fallback quality") # Fall back to a quality (which must be compatible with all other extruders) From 8847325cf8c16eea64a2e4f4e8173a0e2e021163 Mon Sep 17 00:00:00 2001 From: Ruben D Date: Sun, 26 Nov 2017 18:47:58 +0100 Subject: [PATCH 22/24] Remove limit on length for integer arrays The integer arrays were limited because the text in the text field is not properly clipped. I found a fix for that. Fixes #2802. --- resources/qml/Settings/SettingTextField.qml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/resources/qml/Settings/SettingTextField.qml b/resources/qml/Settings/SettingTextField.qml index cdc0588940..64df60b132 100644 --- a/resources/qml/Settings/SettingTextField.qml +++ b/resources/qml/Settings/SettingTextField.qml @@ -1,5 +1,5 @@ -// Copyright (c) 2015 Ultimaker B.V. -// Uranium is released under the terms of the LGPLv3 or higher. +// Copyright (c) 2017 Ultimaker B.V. +// Cura is released under the terms of the LGPLv3 or higher. import QtQuick 2.2 import QtQuick.Controls 1.2 @@ -154,7 +154,7 @@ SettingItem selectByMouse: true; - maximumLength: (definition.type == "[int]") ? 20 : (definition.type == "str") ? -1 : 10; + maximumLength: (definition.type == "str" || definition.type == "[int]") ? -1 : 10; validator: RegExpValidator { regExp: (definition.type == "[int]") ? /^\[?(\s*-?[0-9]{0,9}\s*,)*(\s*-?[0-9]{0,9})\s*\]?$/ : (definition.type == "int") ? /^-?[0-9]{0,10}$/ : (definition.type == "float") ? /^-?[0-9]{0,9}[.,]?[0-9]{0,10}$/ : /^.*$/ } // definition.type property from parent loader used to disallow fractional number entry From 0d0bcb8aeaaa85b8ed36f20b95c6ff64c1d9f4b1 Mon Sep 17 00:00:00 2001 From: Ruben D Date: Sun, 26 Nov 2017 18:48:27 +0100 Subject: [PATCH 23/24] Clip text that exceeds the width of the text box. For #2802. --- resources/qml/Settings/SettingTextField.qml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/resources/qml/Settings/SettingTextField.qml b/resources/qml/Settings/SettingTextField.qml index 64df60b132..8a51f2baff 100644 --- a/resources/qml/Settings/SettingTextField.qml +++ b/resources/qml/Settings/SettingTextField.qml @@ -108,6 +108,7 @@ SettingItem left: parent.left leftMargin: UM.Theme.getSize("setting_unit_margin").width right: parent.right + rightMargin: UM.Theme.getSize("setting_unit_margin").width verticalCenter: parent.verticalCenter } renderType: Text.NativeRendering @@ -155,6 +156,7 @@ SettingItem selectByMouse: true; maximumLength: (definition.type == "str" || definition.type == "[int]") ? -1 : 10; + clip: true; //Hide any text that exceeds the width of the text box. validator: RegExpValidator { regExp: (definition.type == "[int]") ? /^\[?(\s*-?[0-9]{0,9}\s*,)*(\s*-?[0-9]{0,9})\s*\]?$/ : (definition.type == "int") ? /^-?[0-9]{0,10}$/ : (definition.type == "float") ? /^-?[0-9]{0,9}[.,]?[0-9]{0,10}$/ : /^.*$/ } // definition.type property from parent loader used to disallow fractional number entry From 0613b1e4b7589446ee9692c87226dfd9f158a00d Mon Sep 17 00:00:00 2001 From: Jaime van Kessel Date: Mon, 27 Nov 2017 13:00:49 +0100 Subject: [PATCH 24/24] Creating components is now done with the prefab function CURA-4568 --- cura/MachineAction.py | 10 ++-------- plugins/3MFReader/WorkspaceDialog.py | 10 ++-------- plugins/ChangeLogPlugin/ChangeLog.py | 8 ++------ plugins/USBPrinting/USBPrinterOutputDeviceManager.py | 8 ++------ plugins/UserAgreementPlugin/UserAgreement.py | 8 ++------ 5 files changed, 10 insertions(+), 34 deletions(-) diff --git a/cura/MachineAction.py b/cura/MachineAction.py index bc7b17af85..37f09b4efa 100644 --- a/cura/MachineAction.py +++ b/cura/MachineAction.py @@ -73,14 +73,8 @@ class MachineAction(QObject, PluginObject): ## Protected helper to create a view object based on provided QML. def _createViewFromQML(self): - path = QUrl.fromLocalFile(os.path.join(PluginRegistry.getInstance().getPluginPath(self.getPluginId()), self._qml_url)) - self._component = QQmlComponent(Application.getInstance()._engine, path) - self._context = QQmlContext(Application.getInstance()._engine.rootContext()) - self._context.setContextProperty("manager", self) - self._view = self._component.create(self._context) - if self._view is None: - Logger.log("c", "QQmlComponent status %s", self._component.status()) - Logger.log("c", "QQmlComponent error string %s", self._component.errorString()) + path = os.path.join(PluginRegistry.getInstance().getPluginPath(self.getPluginId()), self._qml_url) + self._view = Application.getInstance().createQmlComponent(path, {"manager": self}) @pyqtProperty(QObject, constant = True) def displayItem(self): diff --git a/plugins/3MFReader/WorkspaceDialog.py b/plugins/3MFReader/WorkspaceDialog.py index 151771b25d..95fef78081 100644 --- a/plugins/3MFReader/WorkspaceDialog.py +++ b/plugins/3MFReader/WorkspaceDialog.py @@ -256,14 +256,8 @@ class WorkspaceDialog(QObject): return self._result def _createViewFromQML(self): - path = QUrl.fromLocalFile(os.path.join(PluginRegistry.getInstance().getPluginPath("3MFReader"), self._qml_url)) - self._component = QQmlComponent(Application.getInstance()._engine, path) - self._context = QQmlContext(Application.getInstance()._engine.rootContext()) - self._context.setContextProperty("manager", self) - self._view = self._component.create(self._context) - if self._view is None: - Logger.log("c", "QQmlComponent status %s", self._component.status()) - Logger.log("c", "QQmlComponent error string %s", self._component.errorString()) + path = os.path.join(PluginRegistry.getInstance().getPluginPath("3MFReader"), self._qml_url) + self._view = Application.getInstance().createQmlComponent(path, {"manager": self}) def show(self): # Emit signal so the right thread actually shows the view. diff --git a/plugins/ChangeLogPlugin/ChangeLog.py b/plugins/ChangeLogPlugin/ChangeLog.py index a80779da50..22218bfaeb 100644 --- a/plugins/ChangeLogPlugin/ChangeLog.py +++ b/plugins/ChangeLogPlugin/ChangeLog.py @@ -106,9 +106,5 @@ class ChangeLog(Extension, QObject,): self._changelog_window.hide() def createChangelogWindow(self): - path = QUrl.fromLocalFile(os.path.join(PluginRegistry.getInstance().getPluginPath(self.getPluginId()), "ChangeLog.qml")) - - component = QQmlComponent(Application.getInstance()._engine, path) - self._changelog_context = QQmlContext(Application.getInstance()._engine.rootContext()) - self._changelog_context.setContextProperty("manager", self) - self._changelog_window = component.create(self._changelog_context) + path = os.path.join(PluginRegistry.getInstance().getPluginPath(self.getPluginId()), "ChangeLog.qml") + self._changelog_window = Application.getInstance().createQmlComponent(path, {"manager": self}) diff --git a/plugins/USBPrinting/USBPrinterOutputDeviceManager.py b/plugins/USBPrinting/USBPrinterOutputDeviceManager.py index fe9095a08b..6167356c4b 100644 --- a/plugins/USBPrinting/USBPrinterOutputDeviceManager.py +++ b/plugins/USBPrinting/USBPrinterOutputDeviceManager.py @@ -91,12 +91,8 @@ class USBPrinterOutputDeviceManager(QObject, OutputDevicePlugin, Extension): # This will create the view if its not already created. def spawnFirmwareInterface(self, serial_port): if self._firmware_view is None: - path = QUrl.fromLocalFile(os.path.join(PluginRegistry.getInstance().getPluginPath("USBPrinting"), "FirmwareUpdateWindow.qml")) - component = QQmlComponent(Application.getInstance()._engine, path) - - self._firmware_context = QQmlContext(Application.getInstance()._engine.rootContext()) - self._firmware_context.setContextProperty("manager", self) - self._firmware_view = component.create(self._firmware_context) + path = os.path.join(PluginRegistry.getInstance().getPluginPath("USBPrinting"), "FirmwareUpdateWindow.qml") + self._firmware_view = Application.getInstance().createQmlComponent(path, {"manager": self}) self._firmware_view.show() diff --git a/plugins/UserAgreementPlugin/UserAgreement.py b/plugins/UserAgreementPlugin/UserAgreement.py index f472b6fb13..da225a63b4 100644 --- a/plugins/UserAgreementPlugin/UserAgreement.py +++ b/plugins/UserAgreementPlugin/UserAgreement.py @@ -45,9 +45,5 @@ class UserAgreement(QObject, Extension): CuraApplication.getInstance().setNeedToShowUserAgreement(False) def createUserAgreementWindow(self): - path = QUrl.fromLocalFile(os.path.join(PluginRegistry.getInstance().getPluginPath(self.getPluginId()), "UserAgreement.qml")) - - component = QQmlComponent(Application.getInstance()._engine, path) - self._user_agreement_context = QQmlContext(Application.getInstance()._engine.rootContext()) - self._user_agreement_context.setContextProperty("manager", self) - self._user_agreement_window = component.create(self._user_agreement_context) + path = os.path.join(PluginRegistry.getInstance().getPluginPath(self.getPluginId()), "UserAgreement.qml") + self._user_agreement_window = Application.getInstance().createQmlComponent(path, {"manager": self})