From 00d8427e423b073a10d31e5cc3037dd0978d1696 Mon Sep 17 00:00:00 2001 From: Jack Ha Date: Mon, 7 May 2018 10:30:45 +0200 Subject: [PATCH 1/5] Add sanity check for GlobalStack CURA-5045 --- cura/Settings/ExtruderManager.py | 3 ++- cura/Settings/GlobalStack.py | 17 +++++++++++++++++ cura/Settings/MachineManager.py | 7 +++++-- .../MachineSettingsAction.py | 2 -- 4 files changed, 24 insertions(+), 5 deletions(-) diff --git a/cura/Settings/ExtruderManager.py b/cura/Settings/ExtruderManager.py index c2fe929957..51e7e81fef 100755 --- a/cura/Settings/ExtruderManager.py +++ b/cura/Settings/ExtruderManager.py @@ -402,7 +402,8 @@ class ExtruderManager(QObject): # Register the extruder trains by position for extruder_train in extruder_trains: - self._extruder_trains[global_stack_id][extruder_train.getMetaDataEntry("position")] = extruder_train + extruder_position = extruder_train.getMetaDataEntry("position") + self._extruder_trains[global_stack_id][extruder_position] = extruder_train # regardless of what the next stack is, we have to set it again, because of signal routing. ??? extruder_train.setParent(global_stack) diff --git a/cura/Settings/GlobalStack.py b/cura/Settings/GlobalStack.py index 5d8a4505a5..cea59bcb70 100755 --- a/cura/Settings/GlobalStack.py +++ b/cura/Settings/GlobalStack.py @@ -153,6 +153,23 @@ class GlobalStack(CuraContainerStack): return True + ## Perform some sanity checks on the global stack + # Sanity check for extruders; they must have positions 0 and up to machine_extruder_count - 1 + def isValid(self): + container_registry = ContainerRegistry.getInstance() + extruder_trains = container_registry.findContainerStacks(type = "extruder_train", machine = self.getId()) + + machine_extruder_count = self.getProperty("machine_extruder_count", "value") + extruder_check_position = set() + for extruder_train in extruder_trains: + extruder_position = extruder_train.getMetaDataEntry("position") + extruder_check_position.add(extruder_position) + + for check_position in range(machine_extruder_count): + if str(check_position) not in extruder_check_position: + return False + return True + ## private: global_stack_mime = MimeType( diff --git a/cura/Settings/MachineManager.py b/cura/Settings/MachineManager.py index 14f4f5fc33..c2b1e6dc5f 100755 --- a/cura/Settings/MachineManager.py +++ b/cura/Settings/MachineManager.py @@ -6,6 +6,7 @@ import time #Type hinting. from typing import List, Dict, TYPE_CHECKING, Optional +from UM.ConfigurationErrorMessage import ConfigurationErrorMessage from UM.Scene.Iterator.DepthFirstIterator import DepthFirstIterator from UM.Signal import Signal @@ -165,8 +166,6 @@ class MachineManager(QObject): if active_machine_id != "" and ContainerRegistry.getInstance().findContainerStacksMetadata(id = active_machine_id): # An active machine was saved, so restore it. self.setActiveMachine(active_machine_id) - # Make sure _active_container_stack is properly initiated - ExtruderManager.getInstance().setActiveExtruderIndex(0) def _onOutputDevicesChanged(self) -> None: self._printer_output_devices = [] @@ -357,6 +356,10 @@ class MachineManager(QObject): return global_stack = containers[0] + if not global_stack.isValid(): + # Mark global stack as invalid + ConfigurationErrorMessage.getInstance().addFaultyContainers(global_stack.getId()) + return # We're done here ExtruderManager.getInstance().setActiveExtruderIndex(0) # Switch to first extruder self._global_container_stack = global_stack Application.getInstance().setGlobalContainerStack(global_stack) diff --git a/plugins/MachineSettingsAction/MachineSettingsAction.py b/plugins/MachineSettingsAction/MachineSettingsAction.py index ded59bf934..7d5b317475 100755 --- a/plugins/MachineSettingsAction/MachineSettingsAction.py +++ b/plugins/MachineSettingsAction/MachineSettingsAction.py @@ -56,8 +56,6 @@ class MachineSettingsAction(MachineAction): if self._isEmptyDefinitionChanges(definition_changes_id): return - self._container_registry.removeContainer(definition_changes_id) - def _reset(self): if not self._global_container_stack: return From b5764237473d8a18e416d330536423f901f83c5f Mon Sep 17 00:00:00 2001 From: Diego Prado Gesto Date: Mon, 7 May 2018 11:49:30 +0200 Subject: [PATCH 2/5] Adapt ovewritten method signature --- cura/Settings/ExtruderStack.py | 2 +- cura/Settings/GlobalStack.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/cura/Settings/ExtruderStack.py b/cura/Settings/ExtruderStack.py index 8dcaaf302e..5e944b401f 100644 --- a/cura/Settings/ExtruderStack.py +++ b/cura/Settings/ExtruderStack.py @@ -38,7 +38,7 @@ class ExtruderStack(CuraContainerStack): # # This will set the next stack and ensure that we register this stack as an extruder. @override(ContainerStack) - def setNextStack(self, stack: CuraContainerStack) -> None: + def setNextStack(self, stack: CuraContainerStack, connect_signals: bool = True) -> None: super().setNextStack(stack) stack.addExtruder(self) self.addMetaDataEntry("machine", stack.id) diff --git a/cura/Settings/GlobalStack.py b/cura/Settings/GlobalStack.py index 5d8a4505a5..2e10863a81 100755 --- a/cura/Settings/GlobalStack.py +++ b/cura/Settings/GlobalStack.py @@ -125,7 +125,7 @@ class GlobalStack(CuraContainerStack): # # This will simply raise an exception since the Global stack cannot have a next stack. @override(ContainerStack) - def setNextStack(self, next_stack: ContainerStack) -> None: + def setNextStack(self, stack: CuraContainerStack, connect_signals: bool = True) -> None: raise Exceptions.InvalidOperationError("Global stack cannot have a next stack!") # protected: From 304c23b87e79bd1627b6c62f301ad811bb997517 Mon Sep 17 00:00:00 2001 From: Ghostkeeper Date: Tue, 8 May 2018 10:43:55 +0200 Subject: [PATCH 3/5] Fix check for existence of gcode_dict variable getattr raises an error if it doesn't exist. It doesn't make the variable None or anything. --- plugins/GCodeWriter/GCodeWriter.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/plugins/GCodeWriter/GCodeWriter.py b/plugins/GCodeWriter/GCodeWriter.py index f25e249db1..c01d48be4c 100644 --- a/plugins/GCodeWriter/GCodeWriter.py +++ b/plugins/GCodeWriter/GCodeWriter.py @@ -66,9 +66,9 @@ class GCodeWriter(MeshWriter): active_build_plate = Application.getInstance().getMultiBuildPlateModel().activeBuildPlate scene = Application.getInstance().getController().getScene() - gcode_dict = getattr(scene, "gcode_dict") - if not gcode_dict: + if not hasattr(scene, "gcode_dict"): return False + gcode_dict = getattr(scene, "gcode_dict") gcode_list = gcode_dict.get(active_build_plate, None) if gcode_list is not None: has_settings = False From 9779c41071304a348fb7c41040ff6c7c4e90438e Mon Sep 17 00:00:00 2001 From: Aleksei S Date: Tue, 8 May 2018 10:47:59 +0200 Subject: [PATCH 4/5] Use MimeTypeDatabase to find loaded file extension and set proper project name CURA-5323 --- cura/PrintInformation.py | 33 ++++++++++++++---------------- plugins/3MFReader/ThreeMFReader.py | 10 +++++++++ plugins/GCodeReader/GCodeReader.py | 10 +++++++++ 3 files changed, 35 insertions(+), 18 deletions(-) diff --git a/cura/PrintInformation.py b/cura/PrintInformation.py index 0de57d00e0..6737ebdfb9 100644 --- a/cura/PrintInformation.py +++ b/cura/PrintInformation.py @@ -16,6 +16,7 @@ from UM.Qt.Duration import Duration from UM.Preferences import Preferences from UM.Scene.SceneNode import SceneNode from UM.i18n import i18nCatalog +from UM.MimeTypeDatabase import MimeTypeDatabase catalog = i18nCatalog("cura") @@ -322,7 +323,7 @@ class PrintInformation(QObject): # when a file is opened using the terminal; the filename comes from _onFileLoaded and still contains its # extension. This cuts the extension off if necessary. - name = os.path.splitext(name)[0] + check_name = os.path.splitext(name)[0] filename_parts = os.path.basename(base_name).split(".") # If it's a gcode, also always update the job name @@ -333,25 +334,21 @@ class PrintInformation(QObject): # if this is a profile file, always update the job name # name is "" when I first had some meshes and afterwards I deleted them so the naming should start again - is_empty = name == "" - if is_gcode or is_project_file or (is_empty or (self._base_name == "" and self._base_name != name)): + is_empty = check_name == "" + if is_gcode or is_project_file or (is_empty or (self._base_name == "" and self._base_name != check_name)): # Only take the file name part, Note : file name might have 'dot' in name as well - if is_project_file: - # This is for .curaproject, loaded as project - self._base_name = ".".join(filename_parts) - elif len(filename_parts) > 1: - if "gcode" in filename_parts: - gcode_index = filename_parts.index('gcode') - self._base_name = ".".join(filename_parts[0:gcode_index]) - elif "curaproject" in filename_parts: - #load a project and import only models - curaproject_index = filename_parts.index('curaproject') - self._base_name = ".".join(filename_parts[0:curaproject_index]) - else: - self._base_name = name - else: - self._base_name = name + data = '' + try: + mime_type = MimeTypeDatabase.getMimeTypeForFile(name) + data = mime_type.stripExtension(name) + except: + Logger.log("w", "Unsupported Mime Type Database file extension") + + if data is not None: + self._base_name = data + else: + self._base_name = '' self._updateJobName() diff --git a/plugins/3MFReader/ThreeMFReader.py b/plugins/3MFReader/ThreeMFReader.py index 6c2fb9a59d..9eec09b202 100755 --- a/plugins/3MFReader/ThreeMFReader.py +++ b/plugins/3MFReader/ThreeMFReader.py @@ -15,6 +15,7 @@ from UM.Math.Vector import Vector from UM.Mesh.MeshBuilder import MeshBuilder from UM.Mesh.MeshReader import MeshReader from UM.Scene.GroupDecorator import GroupDecorator +from UM.MimeTypeDatabase import MimeTypeDatabase, MimeType from cura.Settings.ExtruderManager import ExtruderManager from cura.Scene.CuraSceneNode import CuraSceneNode @@ -25,6 +26,15 @@ from cura.Machines.QualityManager import getMachineDefinitionIDForQualitySearch MYPY = False + +MimeTypeDatabase.addMimeType( + MimeType( + name = "application/x-cura-project-file", + comment = "Cura Project File", + suffixes = ["curaproject.3mf"] + ) +) + try: if not MYPY: import xml.etree.cElementTree as ET diff --git a/plugins/GCodeReader/GCodeReader.py b/plugins/GCodeReader/GCodeReader.py index 6f872bc6f7..80a6bea98a 100755 --- a/plugins/GCodeReader/GCodeReader.py +++ b/plugins/GCodeReader/GCodeReader.py @@ -5,10 +5,20 @@ from UM.FileHandler.FileReader import FileReader from UM.Mesh.MeshReader import MeshReader from UM.i18n import i18nCatalog from UM.Preferences import Preferences +from UM.MimeTypeDatabase import MimeTypeDatabase, MimeType catalog = i18nCatalog("cura") from . import MarlinFlavorParser, RepRapFlavorParser + +MimeTypeDatabase.addMimeType( + MimeType( + name = "application/x-cura-gcode-file", + comment = "Cura GCode File", + suffixes = ["gcode", "gcode.gz"] + ) +) + # Class for loading and parsing G-code files class GCodeReader(MeshReader): From d083426497631ea2ab1ca1276121de46cb300726 Mon Sep 17 00:00:00 2001 From: Aleksei S Date: Tue, 8 May 2018 10:59:05 +0200 Subject: [PATCH 5/5] Added MimeTypeDatabase for UFP extension CURA-5323 --- plugins/UFPWriter/__init__.py | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/plugins/UFPWriter/__init__.py b/plugins/UFPWriter/__init__.py index 9db6b042f8..a2ec99044f 100644 --- a/plugins/UFPWriter/__init__.py +++ b/plugins/UFPWriter/__init__.py @@ -11,6 +11,16 @@ except ImportError: from UM.i18n import i18nCatalog #To translate the file format description. from UM.Mesh.MeshWriter import MeshWriter #For the binary mode flag. +from UM.MimeTypeDatabase import MimeTypeDatabase, MimeType + + +MimeTypeDatabase.addMimeType( + MimeType( + name = "application/x-cura-stl-file", + comment = "Cura UFP File", + suffixes = ["ufp"] + ) +) i18n_catalog = i18nCatalog("cura")