From 946b2b943e53e6fb5027f1b1c78bbb8c3ab08692 Mon Sep 17 00:00:00 2001 From: Lipu Fei Date: Tue, 27 Aug 2019 13:38:42 +0200 Subject: [PATCH 1/2] F5 reloads gcode file CURA-6643 --- cura/CuraApplication.py | 14 ++++++++++++++ cura/Scene/GCodeListDecorator.py | 9 ++++++++- plugins/GCodeGzReader/GCodeGzReader.py | 2 +- plugins/GCodeReader/FlavorParser.py | 3 ++- plugins/GCodeReader/GCodeReader.py | 12 ++++++++---- 5 files changed, 33 insertions(+), 7 deletions(-) diff --git a/cura/CuraApplication.py b/cura/CuraApplication.py index d477454e2b..749c8925ff 100755 --- a/cura/CuraApplication.py +++ b/cura/CuraApplication.py @@ -69,6 +69,7 @@ from cura.Scene.BuildPlateDecorator import BuildPlateDecorator from cura.Scene.ConvexHullDecorator import ConvexHullDecorator from cura.Scene.CuraSceneController import CuraSceneController from cura.Scene.CuraSceneNode import CuraSceneNode +from cura.Scene.GCodeListDecorator import GCodeListDecorator from cura.Scene.SliceableObjectDecorator import SliceableObjectDecorator from cura.Scene import ZOffsetDecorator @@ -1327,7 +1328,14 @@ class CuraApplication(QtApplication): Logger.log("i", "Reloading all loaded mesh data.") nodes = [] has_merged_nodes = False + gcode_filename = None # type: Optional[str] for node in DepthFirstIterator(self.getController().getScene().getRoot()): + # Objects loaded from Gcode should also be included. + gcode_list_decorator = node.getDecorator(GCodeListDecorator) + if gcode_list_decorator is not None and gcode_list_decorator.getGcodeFileName(): + gcode_filename = gcode_list_decorator.getGcodeFileName() + break + if not isinstance(node, CuraSceneNode) or not node.getMeshData(): if node.getName() == "MergedMesh": has_merged_nodes = True @@ -1335,11 +1343,17 @@ class CuraApplication(QtApplication): nodes.append(node) + # We can open only one gcode file at the same time. If the current view has a gcode file open, just reopen it + # for reloading. + if gcode_filename: + self._openFile(gcode_filename) + if not nodes: return for node in nodes: mesh_data = node.getMeshData() + gcode_list_decorator = node.getDecorator(GCodeListDecorator) if mesh_data and mesh_data.getFileName(): job = ReadMeshJob(mesh_data.getFileName()) job._node = node # type: ignore diff --git a/cura/Scene/GCodeListDecorator.py b/cura/Scene/GCodeListDecorator.py index d3dadb3f23..6c52fb89bf 100644 --- a/cura/Scene/GCodeListDecorator.py +++ b/cura/Scene/GCodeListDecorator.py @@ -1,11 +1,18 @@ from UM.Scene.SceneNodeDecorator import SceneNodeDecorator -from typing import List +from typing import List, Optional class GCodeListDecorator(SceneNodeDecorator): def __init__(self) -> None: super().__init__() self._gcode_list = [] # type: List[str] + self._filename = None # type: Optional[str] + + def getGcodeFileName(self) -> Optional[str]: + return self._filename + + def setGcodeFileName(self, filename: str) -> None: + self._filename = filename def getGCodeList(self) -> List[str]: return self._gcode_list diff --git a/plugins/GCodeGzReader/GCodeGzReader.py b/plugins/GCodeGzReader/GCodeGzReader.py index d075e4e3b0..a528b494e9 100644 --- a/plugins/GCodeGzReader/GCodeGzReader.py +++ b/plugins/GCodeGzReader/GCodeGzReader.py @@ -27,6 +27,6 @@ class GCodeGzReader(MeshReader): file_data = file.read() uncompressed_gcode = gzip.decompress(file_data).decode("utf-8") PluginRegistry.getInstance().getPluginObject("GCodeReader").preReadFromStream(uncompressed_gcode) - result = PluginRegistry.getInstance().getPluginObject("GCodeReader").readFromStream(uncompressed_gcode) + result = PluginRegistry.getInstance().getPluginObject("GCodeReader").readFromStream(uncompressed_gcode, file_name) return result diff --git a/plugins/GCodeReader/FlavorParser.py b/plugins/GCodeReader/FlavorParser.py index 12bed210d2..fb97525da9 100644 --- a/plugins/GCodeReader/FlavorParser.py +++ b/plugins/GCodeReader/FlavorParser.py @@ -292,7 +292,7 @@ class FlavorParser: extruder.getProperty("machine_nozzle_offset_y", "value")] return result - def processGCodeStream(self, stream: str) -> Optional[CuraSceneNode]: + def processGCodeStream(self, stream: str, filename: str) -> Optional[CuraSceneNode]: Logger.log("d", "Preparing to load GCode") self._cancelled = False # We obtain the filament diameter from the selected extruder to calculate line widths @@ -453,6 +453,7 @@ class FlavorParser: scene_node.addDecorator(decorator) gcode_list_decorator = GCodeListDecorator() + gcode_list_decorator.setGcodeFileName(filename) gcode_list_decorator.setGCodeList(gcode_list) scene_node.addDecorator(gcode_list_decorator) diff --git a/plugins/GCodeReader/GCodeReader.py b/plugins/GCodeReader/GCodeReader.py index b9e948dfea..e0d31c340e 100755 --- a/plugins/GCodeReader/GCodeReader.py +++ b/plugins/GCodeReader/GCodeReader.py @@ -2,12 +2,16 @@ # Copyright (c) 2018 Ultimaker B.V. # Cura is released under the terms of the LGPLv3 or higher. +from typing import Optional + from UM.FileHandler.FileReader import FileReader from UM.Mesh.MeshReader import MeshReader from UM.i18n import i18nCatalog from UM.Application import Application from UM.MimeTypeDatabase import MimeTypeDatabase, MimeType +from cura.Scene.CuraSceneNode import CuraSceneNode + catalog = i18nCatalog("cura") from . import MarlinFlavorParser, RepRapFlavorParser @@ -54,10 +58,10 @@ class GCodeReader(MeshReader): file_data = file.read() return self.preReadFromStream(file_data, args, kwargs) - def readFromStream(self, stream): - return self._flavor_reader.processGCodeStream(stream) + def readFromStream(self, stream: str, filename: str) -> Optional["CuraSceneNode"]: + return self._flavor_reader.processGCodeStream(stream, filename) - def _read(self, file_name): + def _read(self, file_name: str) -> Optional["CuraSceneNode"]: with open(file_name, "r", encoding = "utf-8") as file: file_data = file.read() - return self.readFromStream(file_data) + return self.readFromStream(file_data, file_name) From 79f11286a631e19e23b3966cd771c8aaea28b4cb Mon Sep 17 00:00:00 2001 From: Lipu Fei Date: Tue, 27 Aug 2019 14:09:16 +0200 Subject: [PATCH 2/2] Fix typing CURA-6643 --- cura/CuraApplication.py | 6 ++---- plugins/GCodeReader/FlavorParser.py | 2 +- plugins/GCodeReader/GCodeReader.py | 22 ++++++++++++++++------ 3 files changed, 19 insertions(+), 11 deletions(-) diff --git a/cura/CuraApplication.py b/cura/CuraApplication.py index 749c8925ff..bb64d7fd8e 100755 --- a/cura/CuraApplication.py +++ b/cura/CuraApplication.py @@ -1331,9 +1331,8 @@ class CuraApplication(QtApplication): gcode_filename = None # type: Optional[str] for node in DepthFirstIterator(self.getController().getScene().getRoot()): # Objects loaded from Gcode should also be included. - gcode_list_decorator = node.getDecorator(GCodeListDecorator) - if gcode_list_decorator is not None and gcode_list_decorator.getGcodeFileName(): - gcode_filename = gcode_list_decorator.getGcodeFileName() + gcode_filename = node.callDecoration("getGcodeFileName") + if gcode_filename is not None: break if not isinstance(node, CuraSceneNode) or not node.getMeshData(): @@ -1353,7 +1352,6 @@ class CuraApplication(QtApplication): for node in nodes: mesh_data = node.getMeshData() - gcode_list_decorator = node.getDecorator(GCodeListDecorator) if mesh_data and mesh_data.getFileName(): job = ReadMeshJob(mesh_data.getFileName()) job._node = node # type: ignore diff --git a/plugins/GCodeReader/FlavorParser.py b/plugins/GCodeReader/FlavorParser.py index fb97525da9..09fa2b4502 100644 --- a/plugins/GCodeReader/FlavorParser.py +++ b/plugins/GCodeReader/FlavorParser.py @@ -292,7 +292,7 @@ class FlavorParser: extruder.getProperty("machine_nozzle_offset_y", "value")] return result - def processGCodeStream(self, stream: str, filename: str) -> Optional[CuraSceneNode]: + def processGCodeStream(self, stream: str, filename: str) -> Optional["CuraSceneNode"]: Logger.log("d", "Preparing to load GCode") self._cancelled = False # We obtain the filament diameter from the selected extruder to calculate line widths diff --git a/plugins/GCodeReader/GCodeReader.py b/plugins/GCodeReader/GCodeReader.py index e0d31c340e..21be026cc6 100755 --- a/plugins/GCodeReader/GCodeReader.py +++ b/plugins/GCodeReader/GCodeReader.py @@ -2,7 +2,7 @@ # Copyright (c) 2018 Ultimaker B.V. # Cura is released under the terms of the LGPLv3 or higher. -from typing import Optional +from typing import Optional, Union, List, TYPE_CHECKING from UM.FileHandler.FileReader import FileReader from UM.Mesh.MeshReader import MeshReader @@ -10,11 +10,15 @@ from UM.i18n import i18nCatalog from UM.Application import Application from UM.MimeTypeDatabase import MimeTypeDatabase, MimeType -from cura.Scene.CuraSceneNode import CuraSceneNode - catalog = i18nCatalog("cura") + +from .FlavorParser import FlavorParser from . import MarlinFlavorParser, RepRapFlavorParser +if TYPE_CHECKING: + from UM.Scene.SceneNode import SceneNode + from cura.Scene.CuraSceneNode import CuraSceneNode + # Class for loading and parsing G-code files class GCodeReader(MeshReader): @@ -34,7 +38,7 @@ class GCodeReader(MeshReader): ) self._supported_extensions = [".gcode", ".g"] - self._flavor_reader = None + self._flavor_reader = None # type: Optional[FlavorParser] Application.getInstance().getPreferences().addPreference("gcodereader/show_caution", True) @@ -59,9 +63,15 @@ class GCodeReader(MeshReader): return self.preReadFromStream(file_data, args, kwargs) def readFromStream(self, stream: str, filename: str) -> Optional["CuraSceneNode"]: + if self._flavor_reader is None: + return None return self._flavor_reader.processGCodeStream(stream, filename) - def _read(self, file_name: str) -> Optional["CuraSceneNode"]: + def _read(self, file_name: str) -> Union["SceneNode", List["SceneNode"]]: with open(file_name, "r", encoding = "utf-8") as file: file_data = file.read() - return self.readFromStream(file_data, file_name) + result = [] # type: List[SceneNode] + node = self.readFromStream(file_data, file_name) + if node is not None: + result.append(node) + return result