This commit is contained in:
Ian Paschal 2018-03-26 11:30:59 +02:00
commit 8871ac9955
4 changed files with 143 additions and 132 deletions

View File

@ -2,6 +2,7 @@
# Cura is released under the terms of the LGPLv3 or higher. # Cura is released under the terms of the LGPLv3 or higher.
import copy import copy
import uuid
from UM.Scene.SceneNodeDecorator import SceneNodeDecorator from UM.Scene.SceneNodeDecorator import SceneNodeDecorator
from UM.Signal import Signal, signalemitter from UM.Signal import Signal, signalemitter
@ -34,7 +35,7 @@ class SettingOverrideDecorator(SceneNodeDecorator):
super().__init__() super().__init__()
self._stack = PerObjectContainerStack(container_id = "per_object_stack_" + str(id(self))) self._stack = PerObjectContainerStack(container_id = "per_object_stack_" + str(id(self)))
self._stack.setDirty(False) # This stack does not need to be saved. self._stack.setDirty(False) # This stack does not need to be saved.
user_container = InstanceContainer(container_id = "SettingOverrideInstanceContainer") user_container = InstanceContainer(container_id = self._generateUniqueName())
user_container.addMetaDataEntry("type", "user") user_container.addMetaDataEntry("type", "user")
self._stack.userChanges = user_container self._stack.userChanges = user_container
self._extruder_stack = ExtruderManager.getInstance().getExtruderStack(0).getId() self._extruder_stack = ExtruderManager.getInstance().getExtruderStack(0).getId()
@ -49,12 +50,19 @@ class SettingOverrideDecorator(SceneNodeDecorator):
self.activeExtruderChanged.connect(self._updateNextStack) self.activeExtruderChanged.connect(self._updateNextStack)
self._updateNextStack() self._updateNextStack()
def _generateUniqueName(self):
return "SettingOverrideInstanceContainer-%s" % uuid.uuid1()
def __deepcopy__(self, memo): def __deepcopy__(self, memo):
## Create a fresh decorator object ## Create a fresh decorator object
deep_copy = SettingOverrideDecorator() deep_copy = SettingOverrideDecorator()
## Copy the instance ## Copy the instance
instance_container = copy.deepcopy(self._stack.getContainer(0), memo) instance_container = copy.deepcopy(self._stack.getContainer(0), memo)
# A unique name must be added, or replaceContainer will not replace it
instance_container.setMetaDataEntry("id", self._generateUniqueName)
## Set the copied instance as the first (and only) instance container of the stack. ## Set the copied instance as the first (and only) instance container of the stack.
deep_copy._stack.replaceContainer(0, instance_container) deep_copy._stack.replaceContainer(0, instance_container)

View File

@ -2,15 +2,11 @@
# Cura is released under the terms of the LGPLv3 or higher. # Cura is released under the terms of the LGPLv3 or higher.
import gzip import gzip
import tempfile
from io import StringIO, BufferedIOBase #To write the g-code to a temporary buffer, and for typing. from io import TextIOWrapper
from typing import List
from UM.Logger import Logger
from UM.Mesh.MeshReader import MeshReader #The class we're extending/implementing. from UM.Mesh.MeshReader import MeshReader #The class we're extending/implementing.
from UM.PluginRegistry import PluginRegistry from UM.PluginRegistry import PluginRegistry
from UM.Scene.SceneNode import SceneNode #For typing.
## A file reader that reads gzipped g-code. ## A file reader that reads gzipped g-code.
# #
@ -24,10 +20,8 @@ class GCodeGzReader(MeshReader):
def read(self, file_name): def read(self, file_name):
with open(file_name, "rb") as file: with open(file_name, "rb") as file:
file_data = file.read() file_data = file.read()
uncompressed_gcode = gzip.decompress(file_data) uncompressed_gcode = gzip.decompress(file_data).decode("utf-8")
with tempfile.NamedTemporaryFile() as temp_file: PluginRegistry.getInstance().getPluginObject("GCodeReader").preReadFromStream(uncompressed_gcode)
temp_file.write(uncompressed_gcode) result = PluginRegistry.getInstance().getPluginObject("GCodeReader").readFromStream(uncompressed_gcode)
PluginRegistry.getInstance().getPluginObject("GCodeReader").preRead(temp_file.name)
result = PluginRegistry.getInstance().getPluginObject("GCodeReader").read(temp_file.name)
return result return result

View File

@ -286,8 +286,8 @@ class FlavorParser:
extruder.getProperty("machine_nozzle_offset_y", "value")] extruder.getProperty("machine_nozzle_offset_y", "value")]
return result return result
def processGCodeFile(self, file_name): def processGCodeStream(self, stream):
Logger.log("d", "Preparing to load %s" % file_name) Logger.log("d", "Preparing to load GCode")
self._cancelled = False self._cancelled = False
# We obtain the filament diameter from the selected printer to calculate line widths # We obtain the filament diameter from the selected printer to calculate line widths
self._filament_diameter = Application.getInstance().getGlobalContainerStack().getProperty("material_diameter", "value") self._filament_diameter = Application.getInstance().getGlobalContainerStack().getProperty("material_diameter", "value")
@ -300,19 +300,19 @@ class FlavorParser:
gcode_list = [] gcode_list = []
self._is_layers_in_file = False self._is_layers_in_file = False
Logger.log("d", "Opening file %s" % file_name)
self._extruder_offsets = self._extruderOffsets() # dict with index the extruder number. can be empty self._extruder_offsets = self._extruderOffsets() # dict with index the extruder number. can be empty
with open(file_name, "r") as file: ##############################################################################################
## This part is where the action starts
##############################################################################################
file_lines = 0 file_lines = 0
current_line = 0 current_line = 0
for line in file: for line in stream.split("\n"):
file_lines += 1 file_lines += 1
gcode_list.append(line) gcode_list.append(line)
if not self._is_layers_in_file and line[:len(self._layer_keyword)] == self._layer_keyword: if not self._is_layers_in_file and line[:len(self._layer_keyword)] == self._layer_keyword:
self._is_layers_in_file = True self._is_layers_in_file = True
file.seek(0) # stream.seek(0)
file_step = max(math.floor(file_lines / 100), 1) file_step = max(math.floor(file_lines / 100), 1)
@ -325,7 +325,7 @@ class FlavorParser:
self._message.setProgress(0) self._message.setProgress(0)
self._message.show() self._message.show()
Logger.log("d", "Parsing %s..." % file_name) Logger.log("d", "Parsing Gcode...")
current_position = self._position(0, 0, 0, 0, [0]) current_position = self._position(0, 0, 0, 0, [0])
current_path = [] current_path = []
@ -333,9 +333,9 @@ class FlavorParser:
negative_layers = 0 negative_layers = 0
previous_layer = 0 previous_layer = 0
for line in file: for line in stream.split("\n"):
if self._cancelled: if self._cancelled:
Logger.log("d", "Parsing %s cancelled" % file_name) Logger.log("d", "Parsing Gcode file cancelled")
return None return None
current_line += 1 current_line += 1
@ -441,11 +441,11 @@ class FlavorParser:
gcode_dict = {active_build_plate_id: gcode_list} gcode_dict = {active_build_plate_id: gcode_list}
Application.getInstance().getController().getScene().gcode_dict = gcode_dict Application.getInstance().getController().getScene().gcode_dict = gcode_dict
Logger.log("d", "Finished parsing %s" % file_name) Logger.log("d", "Finished parsing Gcode")
self._message.hide() self._message.hide()
if self._layer_number == 0: if self._layer_number == 0:
Logger.log("w", "File %s doesn't contain any valid layers" % file_name) Logger.log("w", "File doesn't contain any valid layers")
settings = Application.getInstance().getGlobalContainerStack() settings = Application.getInstance().getGlobalContainerStack()
machine_width = settings.getProperty("machine_width", "value") machine_width = settings.getProperty("machine_width", "value")
@ -454,7 +454,7 @@ class FlavorParser:
if not self._center_is_zero: if not self._center_is_zero:
scene_node.setPosition(Vector(-machine_width / 2, 0, machine_depth / 2)) scene_node.setPosition(Vector(-machine_width / 2, 0, machine_depth / 2))
Logger.log("d", "Loaded %s" % file_name) Logger.log("d", "GCode loading finished")
if Preferences.getInstance().getValue("gcodereader/show_caution"): if Preferences.getInstance().getValue("gcodereader/show_caution"):
caution_message = Message(catalog.i18nc( caution_message = Message(catalog.i18nc(

View File

@ -24,10 +24,8 @@ class GCodeReader(MeshReader):
Preferences.getInstance().addPreference("gcodereader/show_caution", True) Preferences.getInstance().addPreference("gcodereader/show_caution", True)
# PreRead is used to get the correct flavor. If not, Marlin is set by default def preReadFromStream(self, stream, *args, **kwargs):
def preRead(self, file_name, *args, **kwargs): for line in stream.split("\n"):
with open(file_name, "r", encoding = "utf-8") as file:
for line in file:
if line[:len(self._flavor_keyword)] == self._flavor_keyword: if line[:len(self._flavor_keyword)] == self._flavor_keyword:
try: try:
self._flavor_reader = self._flavor_readers_dict[line[len(self._flavor_keyword):].rstrip()] self._flavor_reader = self._flavor_readers_dict[line[len(self._flavor_keyword):].rstrip()]
@ -40,5 +38,16 @@ class GCodeReader(MeshReader):
self._flavor_reader = self._flavor_readers_dict[self._flavor_default] self._flavor_reader = self._flavor_readers_dict[self._flavor_default]
return FileReader.PreReadResult.accepted return FileReader.PreReadResult.accepted
# PreRead is used to get the correct flavor. If not, Marlin is set by default
def preRead(self, file_name, *args, **kwargs):
with open(file_name, "r", encoding = "utf-8") as file:
file_data = file.read()
return self.preReadFromStream(file_data, args, kwargs)
def readFromStream(self, stream):
return self._flavor_reader.processGCodeStream(stream)
def read(self, file_name): def read(self, file_name):
return self._flavor_reader.processGCodeFile(file_name) with open(file_name, "r", encoding = "utf-8") as file:
file_data = file.read()
return self.readFromStream(file_data)