class InvalidInstanceError(Exception): pass class IncorrectInstanceVersionError(Exception): pass class DefinitionNotFoundError(Exception): pass MimeTypeDatabase.addMimeType( MimeType(name="application/x-uranium-instancecontainer", comment="Uranium Instance Container", suffixes=["inst.cfg"])) @signalemitter class InstanceContainer(QObject, ContainerInterface, PluginObject): """A container for SettingInstance objects.""" Version = 4 version_regex = re.compile("\nversion ?= ?(\d+)") setting_version_regex = re.compile("\nsetting_version ?= ?(\d+)") type_regex = re.compile("\ntype ?= ?(\w+)") def __init__(self, container_id: str, parent: QObject = None,
Logger.log("w", "There is no firmware for machine %s.", self.getBottom().id) return "" try: return Resources.getPath( cura.CuraApplication.CuraApplication.ResourceTypes.Firmware, hex_file.format(baudrate=baudrate)) except FileNotFoundError: Logger.log("w", "Firmware file %s not found.", hex_file) return "" def getName(self) -> str: return self._metadata.get("group_name", self._metadata.get("name", "")) def setName(self, name: "str") -> None: super().setName(name) nameChanged = pyqtSignal() name = pyqtProperty(str, fget=getName, fset=setName, notify=nameChanged) ## private: global_stack_mime = MimeType(name="application/x-cura-globalstack", comment="Cura Global Stack", suffixes=["global.cfg"]) MimeTypeDatabase.addMimeType(global_stack_mime) ContainerRegistry.addContainerTypeByName(GlobalStack, "global_stack", global_stack_mime.name)
class InvalidDefinitionError(Exception): pass class IncorrectDefinitionVersionError(Exception): pass class InvalidOverrideError(Exception): pass MimeTypeDatabase.addMimeType( MimeType(name="application/x-uranium-definitioncontainer", comment="Uranium Definition Container", suffixes=["def.json"])) ## A container for SettingDefinition objects. # # class DefinitionContainer(QObject, DefinitionContainerInterface, PluginObject): Version = 2 ## Constructor # # \param container_id A unique, machine readable/writable ID for this container. def __init__(self, container_id: str, i18n_catalog: i18nCatalog = None,
def _onPropertiesChanged(self, key, properties): # When there is a setting that is not settable per extruder that depends on a value from a setting that is, # we do not always get properly informed that we should re-evaluate the setting. So make sure to indicate # something changed for those settings. if not self.getNextStack(): return #There are no global settings to depend on. definitions = self.getNextStack().definition.findDefinitions(key=key) if definitions: has_global_dependencies = False for relation in definitions[0].relations: if not getattr(relation.target, "settable_per_extruder", True): has_global_dependencies = True break if has_global_dependencies: self.getNextStack().propertiesChanged.emit(key, properties) def findDefaultVariant(self): # The default variant is defined in the machine stack and/or definition, so use the machine stack to find # the default variant. return self.getNextStack().findDefaultVariant() extruder_stack_mime = MimeType(name="application/x-cura-extruderstack", comment="Cura Extruder Stack", suffixes=["extruder.cfg"]) MimeTypeDatabase.addMimeType(extruder_stack_mime) ContainerRegistry.addContainerTypeByName(ExtruderStack, "extruder_stack", extruder_stack_mime.name)
from . import ContainerInterface from . import SettingFunction class IncorrectVersionError(Exception): pass class InvalidContainerStackError(Exception): pass MimeTypeDatabase.addMimeType( MimeType(name="application/x-uranium-containerstack", comment="Uranium Container Stack", suffixes=["stack.cfg"])) ## A stack of setting containers to handle setting value retrieval. @signalemitter class ContainerStack(ContainerInterface.ContainerInterface, PluginObject): Version = 2 ## Constructor # # \param stack_id \type{string} A unique, machine readable/writable ID. def __init__(self, stack_id, *args, **kwargs): super().__init__(*args, **kwargs) self._id = str(stack_id)
# Uranium is released under the terms of the LGPLv3 or higher. from UM.Mesh.MeshReader import MeshReader from UM.Mesh.MeshBuilder import MeshBuilder from UM.Logger import Logger from UM.Scene.SceneNode import SceneNode from UM.Job import Job from UM.MimeTypeDatabase import MimeTypeDatabase, MimeType import os import struct import numpy MimeTypeDatabase.addMimeType( MimeType(name="application/x-uranium-stl-file", comment="Uranium STL File", suffixes=["stl"])) use_numpystl = False try: import stl # numpy-stl lib import stl.mesh # Increase max count. (10 million should be okay-ish) stl.stl.MAX_COUNT = 10000000 use_numpystl = True except ImportError: Logger.log("w", "Could not find numpy-stl, falling back to slower code.") # We have our own fallback code.
# Copyright (c) 2018 Ultimaker B.V. # Uranium is released under the terms of the LGPLv3 or higher. import configparser from typing import Any, Dict, IO, Optional, Tuple, Union from UM.Decorators import deprecated from UM.Logger import Logger from UM.MimeTypeDatabase import MimeTypeDatabase, MimeType #To register the MIME type of the preference file. from UM.SaveFile import SaveFile from UM.Signal import Signal, signalemitter MimeTypeDatabase.addMimeType( MimeType(name="application/x-uranium-preferences", comment="Uranium Preferences File", suffixes=["cfg"], preferred_suffix="cfg")) ## Preferences are application based settings that are saved for future use. # Typical preferences would be window size, standard machine, etc. # The application preferences can be gotten from the getPreferences() function in Application @signalemitter class Preferences: Version = 6 def __init__(self) -> None: super().__init__() self._parser = None #type: Optional[configparser.ConfigParser] self._preferences = {} #type: Dict[str, Any]
def requestWrite(self, nodes, file_name = None, limit_mimetypes = None, file_handler = None): if self._writing: raise OutputDeviceError.DeviceBusyError() # Set up and display file dialog dialog = QFileDialog() dialog.setWindowTitle(catalog.i18nc("@title:window", "Save to File")) dialog.setFileMode(QFileDialog.AnyFile) dialog.setAcceptMode(QFileDialog.AcceptSave) # Ensure platform never ask for overwrite confirmation since we do this ourselves dialog.setOption(QFileDialog.DontConfirmOverwrite) if sys.platform == "linux" and "KDE_FULL_SESSION" in os.environ: dialog.setOption(QFileDialog.DontUseNativeDialog) filters = [] mime_types = [] selected_filter = None last_used_type = Preferences.getInstance().getValue("local_file/last_used_type") if not file_handler: file_handler = Application.getInstance().getMeshFileHandler() file_types = file_handler.getSupportedFileTypesWrite() file_types.sort(key = lambda k: k["description"]) if limit_mimetypes: file_types = list(filter(lambda i: i["mime_type"] in limit_mimetypes, file_types)) if len(file_types) == 0: Logger.log("e", "There are no file types available to write with!") raise OutputDeviceError.WriteRequestFailedError() for item in file_types: type_filter = "{0} (*.{1})".format(item["description"], item["extension"]) filters.append(type_filter) mime_types.append(item["mime_type"]) if last_used_type == item["mime_type"]: selected_filter = type_filter if file_name: file_name += "." + item["extension"] dialog.setNameFilters(filters) if selected_filter is not None: dialog.selectNameFilter(selected_filter) if file_name is not None: dialog.selectFile(file_name) stored_directory = Preferences.getInstance().getValue("local_file/dialog_save_path") dialog.setDirectory(stored_directory) if not dialog.exec_(): raise OutputDeviceError.UserCanceledError() save_path = dialog.directory().absolutePath() Preferences.getInstance().setValue("local_file/dialog_save_path", save_path) selected_type = file_types[filters.index(dialog.selectedNameFilter())] Preferences.getInstance().setValue("local_file/last_used_type", selected_type["mime_type"]) # Get file name from file dialog file_name = dialog.selectedFiles()[0] Logger.log("d", "Writing to [%s]..." % file_name) # OSX does not handle extensions with multiple periods correctly. if Platform.isOSX(): Logger.log("d", "OS X: checking for double extension...") mime_types = MimeType("", "", [t['extension'] for t in file_types]) # Check if an extension is added multiple times. while mime_types.stripExtension(file_name) != mime_types.stripExtension(mime_types.stripExtension(file_name)): file_name = mime_types.stripExtension(file_name) Logger.log("d", "Multi extension detected, setting filename to [%s]" % file_name) if os.path.exists(file_name): result = QMessageBox.question(None, catalog.i18nc("@title:window", "File Already Exists"), catalog.i18nc("@label", "The file <filename>{0}</filename> already exists. Are you sure you want to overwrite it?").format(file_name)) if result == QMessageBox.No: raise OutputDeviceError.UserCanceledError() self.writeStarted.emit(self) # Actually writing file if file_handler: file_writer = file_handler.getWriter(selected_type["id"]) else: file_writer = Application.getInstance().getMeshFileHandler().getWriter(selected_type["id"]) try: mode = selected_type["mode"] if mode == MeshWriter.OutputMode.TextMode: Logger.log("d", "Writing to Local File %s in text mode", file_name) stream = open(file_name, "wt", encoding = "utf-8") elif mode == MeshWriter.OutputMode.BinaryMode: Logger.log("d", "Writing to Local File %s in binary mode", file_name) stream = open(file_name, "wb") job = WriteFileJob(file_writer, stream, nodes, mode) job.setFileName(file_name) job.progress.connect(self._onJobProgress) job.finished.connect(self._onWriteJobFinished) message = Message(catalog.i18nc("@info:progress", "Saving to <filename>{0}</filename>").format(file_name), 0, False, -1) message.show() job._message = message self._writing = True job.start() except PermissionError as e: Logger.log("e", "Permission denied when trying to write to %s: %s", file_name, str(e)) raise OutputDeviceError.PermissionDeniedError(catalog.i18nc("@info:status", "Permission denied when trying to save <filename>{0}</filename>").format(file_name)) from e except OSError as e: Logger.log("e", "Operating system would not let us write to %s: %s", file_name, str(e)) raise OutputDeviceError.WriteRequestFailedError(catalog.i18nc("@info:status", "Could not save to <filename>{0}</filename>: <message>{1}</message>").format()) from e
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 from cura.Scene.BuildPlateDecorator import BuildPlateDecorator from cura.Scene.SliceableObjectDecorator import SliceableObjectDecorator from cura.Scene.ZOffsetDecorator import ZOffsetDecorator 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 except ImportError: Logger.log("w", "Unable to load cElementTree, switching to slower version") import xml.etree.ElementTree as ET ## Base implementation for reading 3MF files. Has no support for textures. Only loads meshes! class ThreeMFReader(MeshReader): def __init__(self): super().__init__() self._supported_extensions = [".3mf"]
# Cura is released under the terms of the LGPLv3 or higher. 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): _flavor_default = "Marlin" _flavor_keyword = ";FLAVOR:" _flavor_readers_dict = {"RepRap" : RepRapFlavorParser.RepRapFlavorParser(), "Marlin" : MarlinFlavorParser.MarlinFlavorParser()} def __init__(self): super(GCodeReader, self).__init__() self._supported_extensions = [".gcode", ".g"]