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/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/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..f76ac1ab3f 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: @@ -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 436f9814db..78f462d8e9 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.Settings.InstanceContainer import InstanceContainer from UM.Settings.Interfaces import ContainerInterface @@ -167,8 +168,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 = [] @@ -359,6 +358,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/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): 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 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 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")