From d6f116b156c63ab33eb46644d7fdae3e8f429ebe Mon Sep 17 00:00:00 2001 From: Ghostkeeper Date: Thu, 14 Feb 2019 14:03:38 +0100 Subject: [PATCH 01/22] Don't crash on editing metadata entries of non-registered materials Sometimes we need to create a temporary material profile just to save it to file. Contributes to issue CURA-5787. --- plugins/XmlMaterialProfile/XmlMaterialProfile.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/plugins/XmlMaterialProfile/XmlMaterialProfile.py b/plugins/XmlMaterialProfile/XmlMaterialProfile.py index 011941eec7..febec2bd34 100644 --- a/plugins/XmlMaterialProfile/XmlMaterialProfile.py +++ b/plugins/XmlMaterialProfile/XmlMaterialProfile.py @@ -71,7 +71,9 @@ class XmlMaterialProfile(InstanceContainer): material_manager = CuraApplication.getInstance().getMaterialManager() root_material_id = self.getMetaDataEntry("base_file") #if basefile is self.getId, this is a basefile. material_group = material_manager.getMaterialGroup(root_material_id) - + if not material_group: #If the profile is not registered in the registry but loose/temporary, it will not have a base file tree. + super().setMetaDataEntry(key, value) + return # Update the root material container root_material_container = material_group.root_material_node.getContainer() if root_material_container is not None: From cc94441b5439d1b6d378a5bbe07cfdc1a4d5db5e Mon Sep 17 00:00:00 2001 From: Ghostkeeper Date: Thu, 14 Feb 2019 17:45:25 +0100 Subject: [PATCH 02/22] Fix serialising materials with Ultimaker S5 in it Contributes to issue CURA-5787. --- plugins/XmlMaterialProfile/XmlMaterialProfile.py | 2 ++ plugins/XmlMaterialProfile/product_to_id.json | 1 + 2 files changed, 3 insertions(+) diff --git a/plugins/XmlMaterialProfile/XmlMaterialProfile.py b/plugins/XmlMaterialProfile/XmlMaterialProfile.py index febec2bd34..4763205fec 100644 --- a/plugins/XmlMaterialProfile/XmlMaterialProfile.py +++ b/plugins/XmlMaterialProfile/XmlMaterialProfile.py @@ -1167,6 +1167,8 @@ class XmlMaterialProfile(InstanceContainer): with open(product_to_id_file, encoding = "utf-8") as f: product_to_id_map = json.load(f) product_to_id_map = {key: [value] for key, value in product_to_id_map.items()} + #This also loads "Ultimaker S5" -> "ultimaker_s5" even though that is not strictly necessary with the default to change spaces into underscores. + #However it is not always loaded with that default; this mapping is also used in serialize() without that default. return product_to_id_map ## Parse the value of the "material compatible" property. diff --git a/plugins/XmlMaterialProfile/product_to_id.json b/plugins/XmlMaterialProfile/product_to_id.json index 3e7ce9311f..6b78d3fe64 100644 --- a/plugins/XmlMaterialProfile/product_to_id.json +++ b/plugins/XmlMaterialProfile/product_to_id.json @@ -6,6 +6,7 @@ "Ultimaker 2+": "ultimaker2_plus", "Ultimaker 3": "ultimaker3", "Ultimaker 3 Extended": "ultimaker3_extended", + "Ultimaker S5": "ultimaker_s5", "Ultimaker Original": "ultimaker_original", "Ultimaker Original+": "ultimaker_original_plus", "Ultimaker Original Dual Extrusion": "ultimaker_original_dual", From 70cd7518ed477ac09c7fa66e84ff34b1fa17bf4b Mon Sep 17 00:00:00 2001 From: Remco Burema Date: Tue, 19 Feb 2019 10:47:21 +0100 Subject: [PATCH 03/22] Adjust description of Skin Overlap (Percentage). [CURA-6140] --- 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 407923fb4e..8bb6e4983b 100644 --- a/resources/definitions/fdmprinter.def.json +++ b/resources/definitions/fdmprinter.def.json @@ -1792,7 +1792,7 @@ "skin_overlap": { "label": "Skin Overlap Percentage", - "description": "The amount of overlap between the skin and the walls as a percentage of the skin line width. A slight overlap allows the walls to connect firmly to the skin. This is a percentage of the average line widths of the skin lines and the innermost wall.", + "description": "Adjust the position where skin is extruded relative to the walls, as a percentage of the line widths of the skin lines and the innermost wall. A slight overlap allows the walls to connect firmly to the skin. Note that, given an equal skin and wall line-width, any percentage over 50% may already cause any skin to go past the wall, because at that point the position of the nozzle of the skin-extruder may already reach past the middle of the wall.", "unit": "%", "type": "float", "default_value": 5, @@ -1807,7 +1807,7 @@ "skin_overlap_mm": { "label": "Skin Overlap", - "description": "The amount of overlap between the skin and the walls. A slight overlap allows the walls to connect firmly to the skin.", + "description": "Adjust the position where skin is extruded relative to the walls. A slight overlap allows the walls to connect firmly to the skin. Note that, given an equal skin and wall line-width, any value over half the width of the wall may already cause any skin to go past the wall, because at that point the position of the nozzle of the skin-extruder may already reach past the middle of the wall.", "unit": "mm", "type": "float", "default_value": 0.02, From c14aa3686cfb2f747d30939439ac2d94c9d02109 Mon Sep 17 00:00:00 2001 From: Ian Paschal Date: Tue, 19 Feb 2019 12:23:03 +0100 Subject: [PATCH 04/22] Add some new colors to theme Contributes to CL-1247 --- resources/themes/cura-dark/theme.json | 1 + resources/themes/cura-light/theme.json | 1 + 2 files changed, 2 insertions(+) diff --git a/resources/themes/cura-dark/theme.json b/resources/themes/cura-dark/theme.json index 41033e7e75..aed45e8a71 100644 --- a/resources/themes/cura-dark/theme.json +++ b/resources/themes/cura-dark/theme.json @@ -222,6 +222,7 @@ "monitor_text_link": [103, 160, 252, 255], "monitor_icon_primary": [229, 229, 229, 255], "monitor_icon_accent": [51, 53, 54, 255], + "monitor_icon_disabled": [102, 102, 102, 255], "monitor_secondary_button_hover": [80, 80, 80, 255], "monitor_secondary_button": [92, 92, 92, 255], diff --git a/resources/themes/cura-light/theme.json b/resources/themes/cura-light/theme.json index 92308537dd..a0a21c31f3 100644 --- a/resources/themes/cura-light/theme.json +++ b/resources/themes/cura-light/theme.json @@ -397,6 +397,7 @@ "monitor_text_link": [50, 130, 255, 255], "monitor_icon_primary": [10, 8, 80, 255], "monitor_icon_accent": [255, 255, 255, 255], + "monitor_icon_disabled": [238, 238, 238, 255], "monitor_secondary_button_hover": [228, 228, 228, 255], "monitor_secondary_button": [240, 240, 240, 255], From e23dd2dd6b30313bc9db3abefb5d95da3aa7ed1e Mon Sep 17 00:00:00 2001 From: Ian Paschal Date: Tue, 19 Feb 2019 12:23:33 +0100 Subject: [PATCH 05/22] Grey-out buttons when using cloud connection Contributes to CL-1247 (includes some boyscoutin') --- .../resources/qml/CameraButton.qml | 43 +++++++++++-------- .../qml/MonitorContextMenuButton.qml | 4 +- 2 files changed, 26 insertions(+), 21 deletions(-) diff --git a/plugins/UM3NetworkPrinting/resources/qml/CameraButton.qml b/plugins/UM3NetworkPrinting/resources/qml/CameraButton.qml index bf7690ac37..c0369cac0b 100644 --- a/plugins/UM3NetworkPrinting/resources/qml/CameraButton.qml +++ b/plugins/UM3NetworkPrinting/resources/qml/CameraButton.qml @@ -7,34 +7,39 @@ import QtQuick.Controls.Styles 1.3 import UM 1.3 as UM import Cura 1.0 as Cura -Rectangle { +Rectangle +{ id: base property var enabled: true - property var iconSource: null; - color: UM.Theme.getColor("monitor_icon_primary") - height: width; - radius: Math.round(0.5 * width); - width: 24 * screenScaleFactor; + property var iconSource: null + color: enabled ? UM.Theme.getColor("monitor_icon_primary") : UM.Theme.getColor("monitor_icon_disabled") + height: width + radius: Math.round(0.5 * width) + width: 24 * screenScaleFactor - UM.RecolorImage { - id: icon; - anchors { - horizontalCenter: parent.horizontalCenter; - verticalCenter: parent.verticalCenter; + UM.RecolorImage + { + id: icon + anchors + { + horizontalCenter: parent.horizontalCenter + verticalCenter: parent.verticalCenter } - color: UM.Theme.getColor("monitor_icon_accent"); - height: width; - source: iconSource; - width: Math.round(parent.width / 2); + color: UM.Theme.getColor("monitor_icon_accent") + height: width + source: iconSource + width: Math.round(parent.width / 2) } - MouseArea { - id: clickArea; - anchors.fill: parent; + MouseArea + { + id: clickArea + anchors.fill: parent hoverEnabled: base.enabled - onClicked: { + onClicked: + { if (base.enabled) { if (OutputDevice.activeCameraUrl != "") diff --git a/plugins/UM3NetworkPrinting/resources/qml/MonitorContextMenuButton.qml b/plugins/UM3NetworkPrinting/resources/qml/MonitorContextMenuButton.qml index 3e4f1839b6..ba85802809 100644 --- a/plugins/UM3NetworkPrinting/resources/qml/MonitorContextMenuButton.qml +++ b/plugins/UM3NetworkPrinting/resources/qml/MonitorContextMenuButton.qml @@ -11,14 +11,14 @@ Button id: base background: Rectangle { - color: UM.Theme.getColor("viewport_background") // TODO: Theme! + color: enabled ? UM.Theme.getColor("viewport_background") : "transparent" height: base.height opacity: base.down || base.hovered ? 1 : 0 radius: Math.round(0.5 * width) width: base.width } contentItem: Label { - color: UM.Theme.getColor("monitor_text_primary") + color: enabled ? UM.Theme.getColor("monitor_text_primary") : UM.Theme.getColor("monitor_text_disabled") font.pixelSize: 32 * screenScaleFactor horizontalAlignment: Text.AlignHCenter text: base.text From b6b7f8cfce8deae3d6a0ce85ca8cb17186093983 Mon Sep 17 00:00:00 2001 From: Ian Paschal Date: Tue, 19 Feb 2019 12:23:48 +0100 Subject: [PATCH 06/22] Disable queue link when connected to cloud Contributes to CL-1247 --- .../UM3NetworkPrinting/resources/qml/MonitorQueue.qml | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/plugins/UM3NetworkPrinting/resources/qml/MonitorQueue.qml b/plugins/UM3NetworkPrinting/resources/qml/MonitorQueue.qml index c75bd4190f..2a95e57838 100644 --- a/plugins/UM3NetworkPrinting/resources/qml/MonitorQueue.qml +++ b/plugins/UM3NetworkPrinting/resources/qml/MonitorQueue.qml @@ -14,6 +14,10 @@ import Cura 1.0 as Cura */ Item { + // If the printer is a cloud printer or not. Other items base their enabled state off of this boolean. In the future + // they might not need to though. + property bool cloudConnection: Cura.MachineManager.activeMachineIsUsingCloudConnection + Label { id: queuedLabel @@ -42,7 +46,7 @@ Item { id: externalLinkIcon anchors.verticalCenter: manageQueueLabel.verticalCenter - color: UM.Theme.getColor("monitor_text_link") + color: !cloudConnection ? UM.Theme.getColor("monitor_text_link") : UM.Theme.getColor("monitor_text_disabled") source: UM.Theme.getIcon("external_link") width: 16 * screenScaleFactor // TODO: Theme! (Y U NO USE 18 LIKE ALL OTHER ICONS?!) height: 16 * screenScaleFactor // TODO: Theme! (Y U NO USE 18 LIKE ALL OTHER ICONS?!) @@ -67,7 +71,8 @@ Item MouseArea { anchors.fill: manageQueueLabel - hoverEnabled: true + enabled: !cloudConnection + hoverEnabled: enabled onClicked: Cura.MachineManager.printerOutputDevices[0].openPrintJobControlPanel() onEntered: { From 0ef014a542fe29e74cfe1eed30235f88abf9fabb Mon Sep 17 00:00:00 2001 From: Ian Paschal Date: Tue, 19 Feb 2019 12:24:04 +0100 Subject: [PATCH 07/22] Don't show "Review Connection" unless you're on the LAN Contributes to CL-1247 --- plugins/UM3NetworkPrinting/src/UM3OutputDevicePlugin.py | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/plugins/UM3NetworkPrinting/src/UM3OutputDevicePlugin.py b/plugins/UM3NetworkPrinting/src/UM3OutputDevicePlugin.py index e57cd15960..4a08b39c8b 100644 --- a/plugins/UM3NetworkPrinting/src/UM3OutputDevicePlugin.py +++ b/plugins/UM3NetworkPrinting/src/UM3OutputDevicePlugin.py @@ -481,8 +481,10 @@ class UM3OutputDevicePlugin(OutputDevicePlugin): "cloud-flow-completed.svg"), image_caption = i18n_catalog.i18nc("@info:status", "Connected!") ) - self._cloud_flow_complete_message.addAction("", i18n_catalog.i18nc("@action", "Review your connection"), "", "", 1) # TODO: Icon - self._cloud_flow_complete_message.actionTriggered.connect(self._onReviewCloudConnection) + # Don't show the review connection link if we're not on the local network + if self._application.getMachineManager().activeMachineHasNetworkConnection: + self._cloud_flow_complete_message.addAction("", i18n_catalog.i18nc("@action", "Review your connection"), "", "", 1) # TODO: Icon + self._cloud_flow_complete_message.actionTriggered.connect(self._onReviewCloudConnection) self._cloud_flow_complete_message.show() # Set the machine's cloud flow as complete so we don't ask the user again and again for cloud connected printers From 7b3420653e4cb831c95e0786e935ffc645b18928 Mon Sep 17 00:00:00 2001 From: Ian Paschal Date: Tue, 19 Feb 2019 12:27:41 +0100 Subject: [PATCH 08/22] Actually, just hide manage queue on cloud Contributes to CL-1247 --- plugins/UM3NetworkPrinting/resources/qml/MonitorQueue.qml | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/plugins/UM3NetworkPrinting/resources/qml/MonitorQueue.qml b/plugins/UM3NetworkPrinting/resources/qml/MonitorQueue.qml index 2a95e57838..5d824ada97 100644 --- a/plugins/UM3NetworkPrinting/resources/qml/MonitorQueue.qml +++ b/plugins/UM3NetworkPrinting/resources/qml/MonitorQueue.qml @@ -41,12 +41,13 @@ Item } height: 18 * screenScaleFactor // TODO: Theme! width: childrenRect.width + visible: !cloudConnection UM.RecolorImage { id: externalLinkIcon anchors.verticalCenter: manageQueueLabel.verticalCenter - color: !cloudConnection ? UM.Theme.getColor("monitor_text_link") : UM.Theme.getColor("monitor_text_disabled") + color: UM.Theme.getColor("monitor_text_link") source: UM.Theme.getIcon("external_link") width: 16 * screenScaleFactor // TODO: Theme! (Y U NO USE 18 LIKE ALL OTHER ICONS?!) height: 16 * screenScaleFactor // TODO: Theme! (Y U NO USE 18 LIKE ALL OTHER ICONS?!) @@ -72,7 +73,7 @@ Item { anchors.fill: manageQueueLabel enabled: !cloudConnection - hoverEnabled: enabled + hoverEnabled: !cloudConnection onClicked: Cura.MachineManager.printerOutputDevices[0].openPrintJobControlPanel() onEntered: { From 22b70e1a345361674c9fb34fa97c62d807606062 Mon Sep 17 00:00:00 2001 From: Jaime van Kessel Date: Tue, 19 Feb 2019 17:06:48 +0100 Subject: [PATCH 09/22] Ignore sceneChange signals if the camera triggered them in some places These places weren't interested in all changes. They can probably be more strict, but the camera is a really safe bet (and already greatly decreases the number of updates, especially when just moving the camera) --- cura/BuildVolume.py | 11 ++++++----- cura/Machines/Models/MultiBuildPlateModel.py | 4 +++- plugins/ModelChecker/ModelChecker.py | 8 +++++++- 3 files changed, 16 insertions(+), 7 deletions(-) diff --git a/cura/BuildVolume.py b/cura/BuildVolume.py index fb13a32732..d00a28c2bb 100755 --- a/cura/BuildVolume.py +++ b/cura/BuildVolume.py @@ -1,6 +1,6 @@ # Copyright (c) 2018 Ultimaker B.V. # Cura is released under the terms of the LGPLv3 or higher. - +from UM.Scene.Camera import Camera from cura.Scene.CuraSceneNode import CuraSceneNode from cura.Settings.ExtruderManager import ExtruderManager from UM.Application import Application #To modify the maximum zoom level. @@ -112,8 +112,6 @@ class BuildVolume(SceneNode): self._setting_change_timer.setSingleShot(True) self._setting_change_timer.timeout.connect(self._onSettingChangeTimerFinished) - - # Must be after setting _build_volume_message, apparently that is used in getMachineManager. # activeQualityChanged is always emitted after setActiveVariant, setActiveMaterial and setActiveQuality. # Therefore this works. @@ -131,7 +129,9 @@ class BuildVolume(SceneNode): def _onSceneChanged(self, source): if self._global_container_stack: - self._scene_change_timer.start() + # Just ignore the camera scene updates. The build volume won't change because of it! + if not isinstance(source, Camera): + self._scene_change_timer.start() def _onSceneChangeTimerFinished(self): root = self._application.getController().getScene().getRoot() @@ -148,7 +148,7 @@ class BuildVolume(SceneNode): if active_extruder_changed is not None: node.callDecoration("getActiveExtruderChangedSignal").disconnect(self._updateDisallowedAreasAndRebuild) node.decoratorsChanged.disconnect(self._updateNodeListeners) - self._updateDisallowedAreasAndRebuild() # make sure we didn't miss anything before we updated the node listeners + self.rebuild() self._scene_objects = new_scene_objects self._onSettingPropertyChanged("print_sequence", "value") # Create fake event, so right settings are triggered. @@ -667,6 +667,7 @@ class BuildVolume(SceneNode): # ``_updateDisallowedAreas`` method itself shouldn't call ``rebuild``, # since there may be other changes before it needs to be rebuilt, which # would hit performance. + def _updateDisallowedAreasAndRebuild(self): self._updateDisallowedAreas() self._updateRaftThickness() diff --git a/cura/Machines/Models/MultiBuildPlateModel.py b/cura/Machines/Models/MultiBuildPlateModel.py index 958e93837a..22796b4759 100644 --- a/cura/Machines/Models/MultiBuildPlateModel.py +++ b/cura/Machines/Models/MultiBuildPlateModel.py @@ -4,6 +4,7 @@ from PyQt5.QtCore import QTimer, pyqtSignal, pyqtProperty from UM.Application import Application +from UM.Scene.Camera import Camera from UM.Scene.Selection import Selection from UM.Qt.ListModel import ListModel @@ -51,7 +52,8 @@ class MultiBuildPlateModel(ListModel): return self._active_build_plate def _updateSelectedObjectBuildPlateNumbersDelayed(self, *args): - self._update_timer.start() + if not isinstance(args[0], Camera): + self._update_timer.start() def _updateSelectedObjectBuildPlateNumbers(self, *args): result = set() diff --git a/plugins/ModelChecker/ModelChecker.py b/plugins/ModelChecker/ModelChecker.py index d2c2eefac2..1913f39d96 100644 --- a/plugins/ModelChecker/ModelChecker.py +++ b/plugins/ModelChecker/ModelChecker.py @@ -9,6 +9,7 @@ from UM.Application import Application from UM.Extension import Extension from UM.Logger import Logger from UM.Message import Message +from UM.Scene.Camera import Camera from UM.i18n import i18nCatalog from UM.PluginRegistry import PluginRegistry from UM.Scene.Iterator.DepthFirstIterator import DepthFirstIterator @@ -35,7 +36,12 @@ class ModelChecker(QObject, Extension): ## Pass-through to allow UM.Signal to connect with a pyqtSignal. def _onChanged(self, *args, **kwargs): - self.onChanged.emit() + # Ignore camera updates. + if len(args) == 0: + self.onChanged.emit() + return + if not isinstance(args[0], Camera): + self.onChanged.emit() ## Called when plug-ins are initialized. # From 3ad916b5654725f19374c95ea28d3f6413c6d98d Mon Sep 17 00:00:00 2001 From: Simon Edwards Date: Tue, 19 Feb 2019 17:07:09 +0100 Subject: [PATCH 10/22] Fix the path to the pop up images in the monitor tab. --- plugins/UM3NetworkPrinting/src/UM3OutputDevicePlugin.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/plugins/UM3NetworkPrinting/src/UM3OutputDevicePlugin.py b/plugins/UM3NetworkPrinting/src/UM3OutputDevicePlugin.py index 942b417b10..bece666829 100644 --- a/plugins/UM3NetworkPrinting/src/UM3OutputDevicePlugin.py +++ b/plugins/UM3NetworkPrinting/src/UM3OutputDevicePlugin.py @@ -455,7 +455,7 @@ class UM3OutputDevicePlugin(OutputDevicePlugin): self._start_cloud_flow_message = Message( text = i18n_catalog.i18nc("@info:status", "Send and monitor print jobs from anywhere using your Ultimaker account."), lifetime = 0, - image_source = os.path.join(os.path.dirname(os.path.abspath(__file__)), "..", "resources", "svg", + image_source = "file:///" + os.path.join(os.path.dirname(os.path.abspath(__file__)), "..", "resources", "svg", "cloud-flow-start.svg"), image_caption = i18n_catalog.i18nc("@info:status", "Connect to Ultimaker Cloud"), option_text = i18n_catalog.i18nc("@action", "Don't ask me again for this printer."), @@ -477,7 +477,7 @@ class UM3OutputDevicePlugin(OutputDevicePlugin): self._cloud_flow_complete_message = Message( text = i18n_catalog.i18nc("@info:status", "You can now send and monitor print jobs from anywhere using your Ultimaker account."), lifetime = 30, - image_source = os.path.join(os.path.dirname(os.path.abspath(__file__)), "..", "resources", "svg", + image_source = "file:///" + os.path.join(os.path.dirname(os.path.abspath(__file__)), "..", "resources", "svg", "cloud-flow-completed.svg"), image_caption = i18n_catalog.i18nc("@info:status", "Connected!") ) @@ -522,4 +522,4 @@ class UM3OutputDevicePlugin(OutputDevicePlugin): self._cloud_flow_complete_message.hide() self._cloud_flow_complete_message = None - self.checkCloudFlowIsPossible() \ No newline at end of file + self.checkCloudFlowIsPossible() From aef89e2bd3fb5f9faff274be648a9bb2a9ce1c98 Mon Sep 17 00:00:00 2001 From: Jaime van Kessel Date: Tue, 19 Feb 2019 17:40:44 +0100 Subject: [PATCH 11/22] Add few more cases where Camera changes caused un-needed updates --- cura/ObjectsModel.py | 14 ++++++++++---- cura/Scene/CuraSceneController.py | 3 ++- plugins/CuraEngineBackend/CuraEngineBackend.py | 3 ++- 3 files changed, 14 insertions(+), 6 deletions(-) diff --git a/cura/ObjectsModel.py b/cura/ObjectsModel.py index 8354540783..f9f923b31d 100644 --- a/cura/ObjectsModel.py +++ b/cura/ObjectsModel.py @@ -5,6 +5,7 @@ from PyQt5.QtCore import QTimer from UM.Application import Application from UM.Qt.ListModel import ListModel +from UM.Scene.Camera import Camera from UM.Scene.Iterator.DepthFirstIterator import DepthFirstIterator from UM.Scene.SceneNode import SceneNode from UM.Scene.Selection import Selection @@ -19,19 +20,24 @@ class ObjectsModel(ListModel): def __init__(self): super().__init__() - Application.getInstance().getController().getScene().sceneChanged.connect(self._updateDelayed) + Application.getInstance().getController().getScene().sceneChanged.connect(self._updateSceneDelayed) Application.getInstance().getPreferences().preferenceChanged.connect(self._updateDelayed) self._update_timer = QTimer() - self._update_timer.setInterval(100) + self._update_timer.setInterval(200) self._update_timer.setSingleShot(True) self._update_timer.timeout.connect(self._update) self._build_plate_number = -1 def setActiveBuildPlate(self, nr): - self._build_plate_number = nr - self._update() + if self._build_plate_number != nr: + self._build_plate_number = nr + self._update() + + def _updateSceneDelayed(self, source): + if not isinstance(source, Camera): + self._update_timer.start() def _updateDelayed(self, *args): self._update_timer.start() diff --git a/cura/Scene/CuraSceneController.py b/cura/Scene/CuraSceneController.py index 4b19271538..9f26ea7cc3 100644 --- a/cura/Scene/CuraSceneController.py +++ b/cura/Scene/CuraSceneController.py @@ -3,6 +3,7 @@ from UM.Logger import Logger from PyQt5.QtCore import Qt, pyqtSlot, QObject from PyQt5.QtWidgets import QApplication +from UM.Scene.Camera import Camera from cura.ObjectsModel import ObjectsModel from cura.Machines.Models.MultiBuildPlateModel import MultiBuildPlateModel @@ -33,7 +34,7 @@ class CuraSceneController(QObject): source = args[0] else: source = None - if not isinstance(source, SceneNode): + if not isinstance(source, SceneNode) or isinstance(source, Camera): return max_build_plate = self._calcMaxBuildPlate() changed = False diff --git a/plugins/CuraEngineBackend/CuraEngineBackend.py b/plugins/CuraEngineBackend/CuraEngineBackend.py index d5531a2773..aac79f6c28 100755 --- a/plugins/CuraEngineBackend/CuraEngineBackend.py +++ b/plugins/CuraEngineBackend/CuraEngineBackend.py @@ -10,6 +10,7 @@ from time import time from typing import Any, cast, Dict, List, Optional, Set, TYPE_CHECKING from UM.Backend.Backend import Backend, BackendState +from UM.Scene.Camera import Camera from UM.Scene.SceneNode import SceneNode from UM.Signal import Signal from UM.Logger import Logger @@ -476,7 +477,7 @@ class CuraEngineBackend(QObject, Backend): # # \param source The scene node that was changed. def _onSceneChanged(self, source: SceneNode) -> None: - if not isinstance(source, SceneNode): + if not isinstance(source, SceneNode) or isinstance(source, Camera): return # This case checks if the source node is a node that contains GCode. In this case the From b61bf3df4d7cbfc695459b472927f175f48f8740 Mon Sep 17 00:00:00 2001 From: Jaime van Kessel Date: Tue, 19 Feb 2019 17:46:29 +0100 Subject: [PATCH 12/22] Only emit signal if the properties actually changed --- cura/Machines/Models/MultiBuildPlateModel.py | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/cura/Machines/Models/MultiBuildPlateModel.py b/cura/Machines/Models/MultiBuildPlateModel.py index 22796b4759..add960a545 100644 --- a/cura/Machines/Models/MultiBuildPlateModel.py +++ b/cura/Machines/Models/MultiBuildPlateModel.py @@ -35,8 +35,9 @@ class MultiBuildPlateModel(ListModel): self._active_build_plate = -1 def setMaxBuildPlate(self, max_build_plate): - self._max_build_plate = max_build_plate - self.maxBuildPlateChanged.emit() + if self._max_build_plate != max_build_plate: + self._max_build_plate = max_build_plate + self.maxBuildPlateChanged.emit() ## Return the highest build plate number @pyqtProperty(int, notify = maxBuildPlateChanged) @@ -44,8 +45,9 @@ class MultiBuildPlateModel(ListModel): return self._max_build_plate def setActiveBuildPlate(self, nr): - self._active_build_plate = nr - self.activeBuildPlateChanged.emit() + if self._active_build_plate != nr: + self._active_build_plate = nr + self.activeBuildPlateChanged.emit() @pyqtProperty(int, notify = activeBuildPlateChanged) def activeBuildPlate(self): From 3f18b0b974ad8cb297119a22217cef7db9c23f4e Mon Sep 17 00:00:00 2001 From: Jaime van Kessel Date: Tue, 19 Feb 2019 18:00:20 +0100 Subject: [PATCH 13/22] Increase agressiveness of short circuit logic; Just check if the node is slicable That should also filter out platform, buildVolume and convexHulLNodes --- cura/BuildVolume.py | 4 ++-- cura/PlatformPhysics.py | 4 ++-- plugins/CuraEngineBackend/CuraEngineBackend.py | 2 +- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/cura/BuildVolume.py b/cura/BuildVolume.py index d00a28c2bb..aa6b7fb63c 100755 --- a/cura/BuildVolume.py +++ b/cura/BuildVolume.py @@ -129,8 +129,8 @@ class BuildVolume(SceneNode): def _onSceneChanged(self, source): if self._global_container_stack: - # Just ignore the camera scene updates. The build volume won't change because of it! - if not isinstance(source, Camera): + # Ignore anything that is not something we can slice in the first place! + if source.callDecoration("isSliceable"): self._scene_change_timer.start() def _onSceneChangeTimerFinished(self): diff --git a/cura/PlatformPhysics.py b/cura/PlatformPhysics.py index 8ddcdbfb2f..8fffac4501 100755 --- a/cura/PlatformPhysics.py +++ b/cura/PlatformPhysics.py @@ -17,7 +17,6 @@ from cura.Scene import ZOffsetDecorator import random # used for list shuffling - class PlatformPhysics: def __init__(self, controller, volume): super().__init__() @@ -40,8 +39,9 @@ class PlatformPhysics: Application.getInstance().getPreferences().addPreference("physics/automatic_drop_down", True) def _onSceneChanged(self, source): - if not source.getMeshData(): + if not source.callDecoration("isSliceable"): return + self._change_timer.start() def _onChangeTimerFinished(self): diff --git a/plugins/CuraEngineBackend/CuraEngineBackend.py b/plugins/CuraEngineBackend/CuraEngineBackend.py index aac79f6c28..ceba5f3006 100755 --- a/plugins/CuraEngineBackend/CuraEngineBackend.py +++ b/plugins/CuraEngineBackend/CuraEngineBackend.py @@ -477,7 +477,7 @@ class CuraEngineBackend(QObject, Backend): # # \param source The scene node that was changed. def _onSceneChanged(self, source: SceneNode) -> None: - if not isinstance(source, SceneNode) or isinstance(source, Camera): + if not source.callDecoration("isSliceable"): return # This case checks if the source node is a node that contains GCode. In this case the From 43b1c869201975dd530e083b5661a1cdfb9d347a Mon Sep 17 00:00:00 2001 From: Simon Edwards Date: Wed, 20 Feb 2019 09:31:51 +0100 Subject: [PATCH 14/22] Use QUrl.fromLocalFile() to create the file:// URLs for the images --- plugins/UM3NetworkPrinting/src/UM3OutputDevicePlugin.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/plugins/UM3NetworkPrinting/src/UM3OutputDevicePlugin.py b/plugins/UM3NetworkPrinting/src/UM3OutputDevicePlugin.py index bece666829..ceeeec0382 100644 --- a/plugins/UM3NetworkPrinting/src/UM3OutputDevicePlugin.py +++ b/plugins/UM3NetworkPrinting/src/UM3OutputDevicePlugin.py @@ -455,8 +455,8 @@ class UM3OutputDevicePlugin(OutputDevicePlugin): self._start_cloud_flow_message = Message( text = i18n_catalog.i18nc("@info:status", "Send and monitor print jobs from anywhere using your Ultimaker account."), lifetime = 0, - image_source = "file:///" + os.path.join(os.path.dirname(os.path.abspath(__file__)), "..", "resources", "svg", - "cloud-flow-start.svg"), + image_source = QUrl.fromLocalFile(os.path.join(os.path.dirname(os.path.abspath(__file__)), "..", + "resources", "svg", "cloud-flow-start.svg")), image_caption = i18n_catalog.i18nc("@info:status", "Connect to Ultimaker Cloud"), option_text = i18n_catalog.i18nc("@action", "Don't ask me again for this printer."), option_state = False @@ -477,8 +477,8 @@ class UM3OutputDevicePlugin(OutputDevicePlugin): self._cloud_flow_complete_message = Message( text = i18n_catalog.i18nc("@info:status", "You can now send and monitor print jobs from anywhere using your Ultimaker account."), lifetime = 30, - image_source = "file:///" + os.path.join(os.path.dirname(os.path.abspath(__file__)), "..", "resources", "svg", - "cloud-flow-completed.svg"), + image_source = QUrl.fromLocalFile(os.path.join(os.path.dirname(os.path.abspath(__file__)), "..", + "resources", "svg", "cloud-flow-completed.svg")), image_caption = i18n_catalog.i18nc("@info:status", "Connected!") ) self._cloud_flow_complete_message.addAction("", i18n_catalog.i18nc("@action", "Review your connection"), "", "", 1) # TODO: Icon From 1608adde000dc71910a73e95c3aedcb776e7f0a6 Mon Sep 17 00:00:00 2001 From: Remco Burema Date: Wed, 20 Feb 2019 09:57:48 +0100 Subject: [PATCH 15/22] Change of wording Skin Overlap (Percentage). [CURA-6140] --- 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 8bb6e4983b..04c69c9497 100644 --- a/resources/definitions/fdmprinter.def.json +++ b/resources/definitions/fdmprinter.def.json @@ -1792,7 +1792,7 @@ "skin_overlap": { "label": "Skin Overlap Percentage", - "description": "Adjust the position where skin is extruded relative to the walls, as a percentage of the line widths of the skin lines and the innermost wall. A slight overlap allows the walls to connect firmly to the skin. Note that, given an equal skin and wall line-width, any percentage over 50% may already cause any skin to go past the wall, because at that point the position of the nozzle of the skin-extruder may already reach past the middle of the wall.", + "description": "Adjust the amount of overlap between the walls and (the endpoints of) the skin-centerlines, as a percentage of the line widths of the skin lines and the innermost wall. A slight overlap allows the walls to connect firmly to the skin. Note that, given an equal skin and wall line-width, any percentage over 50% may already cause any skin to go past the wall, because at that point the position of the nozzle of the skin-extruder may already reach past the middle of the wall.", "unit": "%", "type": "float", "default_value": 5, @@ -1807,7 +1807,7 @@ "skin_overlap_mm": { "label": "Skin Overlap", - "description": "Adjust the position where skin is extruded relative to the walls. A slight overlap allows the walls to connect firmly to the skin. Note that, given an equal skin and wall line-width, any value over half the width of the wall may already cause any skin to go past the wall, because at that point the position of the nozzle of the skin-extruder may already reach past the middle of the wall.", + "description": "Adjust the amount of overlap between the walls and (the endpoints of) the skin-centerlines. A slight overlap allows the walls to connect firmly to the skin. Note that, given an equal skin and wall line-width, any value over half the width of the wall may already cause any skin to go past the wall, because at that point the position of the nozzle of the skin-extruder may already reach past the middle of the wall.", "unit": "mm", "type": "float", "default_value": 0.02, From a11878b1991401a3dd24e5518eaa27e19838875c Mon Sep 17 00:00:00 2001 From: Ian Paschal Date: Wed, 20 Feb 2019 10:40:23 +0100 Subject: [PATCH 16/22] Log warning instead of exception if no connection Contributes to CL-1245 --- cura/OAuth2/AuthorizationHelpers.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cura/OAuth2/AuthorizationHelpers.py b/cura/OAuth2/AuthorizationHelpers.py index f125876879..bf70bf693a 100644 --- a/cura/OAuth2/AuthorizationHelpers.py +++ b/cura/OAuth2/AuthorizationHelpers.py @@ -92,7 +92,7 @@ class AuthorizationHelpers: }) except requests.exceptions.ConnectionError: # Connection was suddenly dropped. Nothing we can do about that. - Logger.logException("e", "Something failed while attempting to parse the JWT token") + Logger.log("w", "Something failed while attempting to parse the JWT token") return None if token_request.status_code not in (200, 201): Logger.log("w", "Could not retrieve token data from auth server: %s", token_request.text) From 09fe06b8bf463fd0805fa767bbe34087adc0c700 Mon Sep 17 00:00:00 2001 From: Ian Paschal Date: Wed, 20 Feb 2019 10:45:36 +0100 Subject: [PATCH 17/22] Add some kaizen changes from #5328 Contributes to CL-1245 --- cura/OAuth2/AuthorizationService.py | 6 +----- plugins/UM3NetworkPrinting/src/Cloud/CloudApiClient.py | 6 +++++- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/cura/OAuth2/AuthorizationService.py b/cura/OAuth2/AuthorizationService.py index 3c2f66d037..442c5d388d 100644 --- a/cura/OAuth2/AuthorizationService.py +++ b/cura/OAuth2/AuthorizationService.py @@ -66,11 +66,7 @@ class AuthorizationService: # \sa _parseJWT def getUserProfile(self) -> Optional["UserProfile"]: if not self._user_profile: - try: - self._user_profile = self._parseJWT() - except requests.exceptions.ConnectionError: - # Unable to get connection, can't login. - return None + self._user_profile = self._parseJWT() if not self._user_profile and self._auth_data: # If there is still no user profile from the JWT, we have to log in again. diff --git a/plugins/UM3NetworkPrinting/src/Cloud/CloudApiClient.py b/plugins/UM3NetworkPrinting/src/Cloud/CloudApiClient.py index adff94bbbc..87c7a50838 100644 --- a/plugins/UM3NetworkPrinting/src/Cloud/CloudApiClient.py +++ b/plugins/UM3NetworkPrinting/src/Cloud/CloudApiClient.py @@ -159,9 +159,13 @@ class CloudApiClient: model: Type[CloudApiClientModel], ) -> None: def parse() -> None: + # Don't try to parse the reply if we didn't get one + if reply.attribute(QNetworkRequest.HttpStatusCodeAttribute) is None: + return status_code, response = self._parseReply(reply) self._anti_gc_callbacks.remove(parse) - return self._parseModels(response, on_finished, model) + self._parseModels(response, on_finished, model) + return self._anti_gc_callbacks.append(parse) reply.finished.connect(parse) From cb8804b86a5ee2faafa256ddb8b0107d641e68d0 Mon Sep 17 00:00:00 2001 From: Ian Paschal Date: Wed, 20 Feb 2019 10:46:15 +0100 Subject: [PATCH 18/22] Revert "Add some kaizen changes from #5328" This reverts commit 09fe06b8bf463fd0805fa767bbe34087adc0c700. --- cura/OAuth2/AuthorizationService.py | 6 +++++- plugins/UM3NetworkPrinting/src/Cloud/CloudApiClient.py | 6 +----- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/cura/OAuth2/AuthorizationService.py b/cura/OAuth2/AuthorizationService.py index 442c5d388d..3c2f66d037 100644 --- a/cura/OAuth2/AuthorizationService.py +++ b/cura/OAuth2/AuthorizationService.py @@ -66,7 +66,11 @@ class AuthorizationService: # \sa _parseJWT def getUserProfile(self) -> Optional["UserProfile"]: if not self._user_profile: - self._user_profile = self._parseJWT() + try: + self._user_profile = self._parseJWT() + except requests.exceptions.ConnectionError: + # Unable to get connection, can't login. + return None if not self._user_profile and self._auth_data: # If there is still no user profile from the JWT, we have to log in again. diff --git a/plugins/UM3NetworkPrinting/src/Cloud/CloudApiClient.py b/plugins/UM3NetworkPrinting/src/Cloud/CloudApiClient.py index 87c7a50838..adff94bbbc 100644 --- a/plugins/UM3NetworkPrinting/src/Cloud/CloudApiClient.py +++ b/plugins/UM3NetworkPrinting/src/Cloud/CloudApiClient.py @@ -159,13 +159,9 @@ class CloudApiClient: model: Type[CloudApiClientModel], ) -> None: def parse() -> None: - # Don't try to parse the reply if we didn't get one - if reply.attribute(QNetworkRequest.HttpStatusCodeAttribute) is None: - return status_code, response = self._parseReply(reply) self._anti_gc_callbacks.remove(parse) - self._parseModels(response, on_finished, model) - return + return self._parseModels(response, on_finished, model) self._anti_gc_callbacks.append(parse) reply.finished.connect(parse) From 9a1d8ea5f9d1922bfb050e2dd69d7d15501b2258 Mon Sep 17 00:00:00 2001 From: Jaime van Kessel Date: Wed, 20 Feb 2019 10:46:49 +0100 Subject: [PATCH 19/22] Don't serialize "definition" for material profile CURA-5787 --- plugins/XmlMaterialProfile/XmlMaterialProfile.py | 12 +----------- 1 file changed, 1 insertion(+), 11 deletions(-) diff --git a/plugins/XmlMaterialProfile/XmlMaterialProfile.py b/plugins/XmlMaterialProfile/XmlMaterialProfile.py index 011941eec7..7f31f93ac0 100644 --- a/plugins/XmlMaterialProfile/XmlMaterialProfile.py +++ b/plugins/XmlMaterialProfile/XmlMaterialProfile.py @@ -141,23 +141,13 @@ class XmlMaterialProfile(InstanceContainer): # setting_version is derived from the "version" tag in the schema, so don't serialize it into a file if ignored_metadata_keys is None: ignored_metadata_keys = set() - ignored_metadata_keys |= {"setting_version"} + ignored_metadata_keys |= {"setting_version", "definition", "status", "variant", "type", "base_file", "approximate_diameter", "id", "container_type", "name"} # remove the keys that we want to ignore in the metadata for key in ignored_metadata_keys: if key in metadata: del metadata[key] properties = metadata.pop("properties", {}) - # Metadata properties that should not be serialized. - metadata.pop("status", "") - metadata.pop("variant", "") - metadata.pop("type", "") - metadata.pop("base_file", "") - metadata.pop("approximate_diameter", "") - metadata.pop("id", "") - metadata.pop("container_type", "") - metadata.pop("name", "") - ## Begin Name Block builder.start("name") # type: ignore From a5761cb56bc305401fb16059661cbcbd855f3a2d Mon Sep 17 00:00:00 2001 From: Ian Paschal Date: Wed, 20 Feb 2019 14:08:13 +0100 Subject: [PATCH 20/22] Use new property names for cloud connection detection --- plugins/MonitorStage/MonitorMain.qml | 2 +- plugins/UM3NetworkPrinting/resources/qml/MonitorQueue.qml | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/plugins/MonitorStage/MonitorMain.qml b/plugins/MonitorStage/MonitorMain.qml index a73650ed6a..ae7923656b 100644 --- a/plugins/MonitorStage/MonitorMain.qml +++ b/plugins/MonitorStage/MonitorMain.qml @@ -11,7 +11,7 @@ Rectangle { id: viewportOverlay - property bool isConnected: Cura.MachineManager.activeMachineHasActiveNetworkConnection || Cura.MachineManager.activeMachineHasActiveCloudConnection + property bool isConnected: Cura.MachineManager.activeMachineIsUsingCloudConnection property bool isNetworkConfigurable: ["Ultimaker 3", "Ultimaker 3 Extended", "Ultimaker S5"].indexOf(Cura.MachineManager.activeMachineDefinitionName) > -1 property bool isNetworkConfigured: { diff --git a/plugins/UM3NetworkPrinting/resources/qml/MonitorQueue.qml b/plugins/UM3NetworkPrinting/resources/qml/MonitorQueue.qml index 5d824ada97..6eaff20f71 100644 --- a/plugins/UM3NetworkPrinting/resources/qml/MonitorQueue.qml +++ b/plugins/UM3NetworkPrinting/resources/qml/MonitorQueue.qml @@ -171,11 +171,11 @@ Item // When printing over the cloud we don't recieve print jobs until there is one, so // unless there's at least one print job we'll be stuck with skeleton loading // indefinitely. - if (Cura.MachineManager.activeMachineHasActiveCloudConnection) + if (Cura.MachineManager.activeMachineIsUsingCloudConnection || OutputDevice.receivedPrintJobs) { return OutputDevice.queuedPrintJobs } - return OutputDevice.receivedPrintJobs ? OutputDevice.queuedPrintJobs : [null,null] + return [null, null] } spacing: 6 // TODO: Theme! } From 10f0a5663d1cb47203c3e63e41b0c09dc6f3d6bf Mon Sep 17 00:00:00 2001 From: Ian Paschal Date: Wed, 20 Feb 2019 14:32:19 +0100 Subject: [PATCH 21/22] Update MonitorMain.qml --- plugins/MonitorStage/MonitorMain.qml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/MonitorStage/MonitorMain.qml b/plugins/MonitorStage/MonitorMain.qml index ae7923656b..88193737bb 100644 --- a/plugins/MonitorStage/MonitorMain.qml +++ b/plugins/MonitorStage/MonitorMain.qml @@ -11,7 +11,7 @@ Rectangle { id: viewportOverlay - property bool isConnected: Cura.MachineManager.activeMachineIsUsingCloudConnection + property bool isConnected: Cura.MachineManager.activeMachineHasNetworkConnection || Cura.MachineManager.activeMachineHasCloudConnection property bool isNetworkConfigurable: ["Ultimaker 3", "Ultimaker 3 Extended", "Ultimaker S5"].indexOf(Cura.MachineManager.activeMachineDefinitionName) > -1 property bool isNetworkConfigured: { From ab25bcaf2f361ae115a331a6fe694ad48c72848a Mon Sep 17 00:00:00 2001 From: Remco Burema Date: Thu, 21 Feb 2019 08:54:05 +0100 Subject: [PATCH 22/22] Tiny fix tranlation typo Spanish (X -> Y). --- resources/i18n/es_ES/fdmprinter.def.json.po | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/resources/i18n/es_ES/fdmprinter.def.json.po b/resources/i18n/es_ES/fdmprinter.def.json.po index bd4ad9fd7f..3b519e7aec 100644 --- a/resources/i18n/es_ES/fdmprinter.def.json.po +++ b/resources/i18n/es_ES/fdmprinter.def.json.po @@ -1604,7 +1604,7 @@ msgstr "El patrĂ³n de relleno se mueve esta distancia a lo largo del eje X." #: fdmprinter.def.json msgctxt "infill_offset_y label" msgid "Infill Y Offset" -msgstr "Desplazamiento del relleno sobre el eje X" +msgstr "Desplazamiento del relleno sobre el eje Y" #: fdmprinter.def.json msgctxt "infill_offset_y description"