def requestWrite(self, nodes, file_name=None, limit_mimetypes=False, file_handler=None, filter_by_machine=False, **kwargs) -> None: if self._progress.visible or self._need_auth.visible or self._writing: return self.writeStarted.emit(self) self._writing = True self._gcode_stream = StringIO() job = WriteFileJob(SM2GCodeWriter(), self._gcode_stream, nodes, SM2GCodeWriter.OutputMode.TextMode) job.finished.connect(self._onWriteJobFinished) message = Message(title="Preparing for upload", progress=-1, lifetime=0, dismissable=False, use_inactivity_timer=False) message.show() job.setMessage(message) job.start()
def _sendPrintJob(self, writer: FileWriter, preferred_format: Dict, nodes: List[SceneNode]): Logger.log("i", "Sending print job to printer.") if self._sending_gcode: self._error_message = Message( i18n_catalog.i18nc("@info:status", "Sending new jobs (temporarily) blocked, still sending the previous print job.")) self._error_message.show() yield #Wait on the user to select a target printer. yield #Wait for the write job to be finished. yield False #Return whether this was a success or not. yield #Prevent StopIteration. self._sending_gcode = True target_printer = yield #Potentially wait on the user to select a target printer. # Using buffering greatly reduces the write time for many lines of gcode if preferred_format["mode"] == FileWriter.OutputMode.TextMode: stream = io.StringIO() else: #Binary mode. stream = io.BytesIO() job = WriteFileJob(writer, stream, nodes, preferred_format["mode"]) self._write_job_progress_message = Message(i18n_catalog.i18nc("@info:status", "Sending data to printer"), lifetime = 0, dismissable = False, progress = -1, title = i18n_catalog.i18nc("@info:title", "Sending Data"), use_inactivity_timer = False) self._write_job_progress_message.show() self._dummy_lambdas = (target_printer, preferred_format, stream) job.finished.connect(self._sendPrintJobWaitOnWriteJobFinished) job.start() yield True #Return that we had success! yield #To prevent having to catch the StopIteration exception.
def _sendPrintJob(self, mesh_format: MeshFormatHandler, nodes: List[SceneNode]): Logger.log("i", "Sending print job to printer.") if self._sending_gcode: self._error_message = Message( i18n_catalog.i18nc("@info:status", "Sending new jobs (temporarily) blocked, still sending the previous print job.")) self._error_message.show() yield #Wait on the user to select a target printer. yield #Wait for the write job to be finished. yield False #Return whether this was a success or not. yield #Prevent StopIteration. self._sending_gcode = True # Potentially wait on the user to select a target printer. target_printer = yield # type: Optional[str] # Using buffering greatly reduces the write time for many lines of gcode stream = mesh_format.createStream() job = WriteFileJob(mesh_format.writer, stream, nodes, mesh_format.file_mode) self._write_job_progress_message = Message(i18n_catalog.i18nc("@info:status", "Sending data to printer"), lifetime = 0, dismissable = False, progress = -1, title = i18n_catalog.i18nc("@info:title", "Sending Data"), use_inactivity_timer = False) self._write_job_progress_message.show() if mesh_format.preferred_format is not None: self._dummy_lambdas = (target_printer, mesh_format.preferred_format, stream) job.finished.connect(self._sendPrintJobWaitOnWriteJobFinished) job.start() yield True # Return that we had success! yield # To prevent having to catch the StopIteration exception.
def _sendPrintJob(self, writer: FileWriter, preferred_format: Dict, nodes: List[SceneNode]): Logger.log("i", "Sending print job to printer.") if self._sending_gcode: self._error_message = Message( i18n_catalog.i18nc("@info:status", "Sending new jobs (temporarily) blocked, still sending the previous print job.")) self._error_message.show() yield #Wait on the user to select a target printer. yield #Wait for the write job to be finished. yield False #Return whether this was a success or not. yield #Prevent StopIteration. self._sending_gcode = True target_printer = yield #Potentially wait on the user to select a target printer. # Using buffering greatly reduces the write time for many lines of gcode stream = io.BytesIO() # type: Union[io.BytesIO, io.StringIO]# Binary mode. if preferred_format["mode"] == FileWriter.OutputMode.TextMode: stream = io.StringIO() job = WriteFileJob(writer, stream, nodes, preferred_format["mode"]) self._write_job_progress_message = Message(i18n_catalog.i18nc("@info:status", "Sending data to printer"), lifetime = 0, dismissable = False, progress = -1, title = i18n_catalog.i18nc("@info:title", "Sending Data"), use_inactivity_timer = False) self._write_job_progress_message.show() self._dummy_lambdas = (target_printer, preferred_format, stream) job.finished.connect(self._sendPrintJobWaitOnWriteJobFinished) job.start() yield True #Return that we had success! yield #To prevent having to catch the StopIteration exception.
def _sendPrintJob(self, writer: FileWriter, preferred_format: Dict, nodes: List[SceneNode]): Logger.log("i", "Sending print job to printer.") if self._sending_gcode: self._error_message = Message( i18n_catalog.i18nc("@info:status", "Sending new jobs (temporarily) blocked, still sending the previous print job.")) self._error_message.show() yield #Wait on the user to select a target printer. yield #Wait for the write job to be finished. yield False #Return whether this was a success or not. yield #Prevent StopIteration. self._sending_gcode = True target_printer = yield #Potentially wait on the user to select a target printer. # Using buffering greatly reduces the write time for many lines of gcode if preferred_format["mode"] == FileWriter.OutputMode.TextMode: stream = io.StringIO() else: #Binary mode. stream = io.BytesIO() job = WriteFileJob(writer, stream, nodes, preferred_format["mode"]) self._progress_message = Message(i18n_catalog.i18nc("@info:status", "Sending data to printer"), lifetime = 0, dismissable = False, progress = -1, title = i18n_catalog.i18nc("@info:title", "Sending Data")) self._progress_message.addAction("Abort", i18n_catalog.i18nc("@action:button", "Cancel"), icon = None, description = "") self._progress_message.actionTriggered.connect(self._progressMessageActionTriggered) self._progress_message.show() job.start() parts = [] # If a specific printer was selected, it should be printed with that machine. if target_printer: target_printer = self._printer_uuid_to_unique_name_mapping[target_printer] parts.append(self._createFormPart("name=require_printer_name", bytes(target_printer, "utf-8"), "text/plain")) # Add user name to the print_job parts.append(self._createFormPart("name=owner", bytes(self._getUserName(), "utf-8"), "text/plain")) file_name = Application.getInstance().getPrintInformation().jobName + "." + preferred_format["extension"] while not job.isFinished(): sleep(0.1) output = stream.getvalue() #Either str or bytes depending on the output mode. if isinstance(stream, io.StringIO): output = output.encode("utf-8") parts.append(self._createFormPart("name=\"file\"; filename=\"%s\"" % file_name, output)) self._latest_reply_handler = self.postFormWithParts("print_jobs/", parts, onFinished=self._onPostPrintJobFinished, onProgress=self._onUploadPrintJobProgress) yield True #Return that we had success! yield #To prevent having to catch the StopIteration exception.
def requestWrite(self, nodes, file_name=None, limit_mimetypes=None, file_handler=None, **kwargs): #The file handler is an object that provides serialisation of file types. #There's several types of files. If not provided, it is assumed that we want to save meshes. if not file_handler: file_handler = Application.getInstance().getMeshFileHandler() file_types = file_handler.getSupportedFileTypesWrite() if not file_types: Logger.log("e", "No supported file types for writing.") file_type = file_types[ 0] #For this example, we'll just pick an arbitrary file type. Normally you may want to choose the device's preferred type or let the user choose. file_writer = file_handler.getWriterByMimeType( file_type["mime_type"] ) #This is the object that will serialize our file for us. if not file_writer: raise WriteRequestFailedError( "Can't find any file writer for the file type {file_type}.". format(file_type=file_type)) #For this example, we will write to a file in a fixed location. output_file_name = os.path.expanduser("~/output.txt") file_stream = open(output_file_name, "w", encoding="utf-8") job = WriteFileJob( file_writer, file_stream, nodes, file_type["mode"] ) #We'll create a WriteFileJob, which gets run asynchronously in the background. job.progress.connect( self._onProgress ) #You can listen to the event for when it's done and when it's progressing. job.finished.connect( self._onFinished) #This way we can properly close the file stream. job.start()
def requestWrite(self, nodes, file_name=None, limit_mimetypes=None, file_handler=None, **kwargs): application = cast(CuraApplication, Application.getInstance()) machine_manager = application.getMachineManager() global_stack = machine_manager.activeMachine filename_format = Application.getInstance().getPreferences().getValue( "gcode_filename_format/filename_format") Logger.log("d", "filename_format = %s", filename_format) if filename_format is "": filename_format = DEFAULT_FILENAME_FORMAT if self._writing: raise OutputDeviceError.DeviceBusyError() self.getModifiedPrintSettings(application, global_stack) dialog = QFileDialog() dialog.setWindowTitle(catalog.i18nc("@title:window", "Save to File")) dialog.setFileMode(QFileDialog.AnyFile) dialog.setAcceptMode(QFileDialog.AcceptSave) 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 if "preferred_mimetypes" in kwargs and kwargs[ "preferred_mimetypes"] is not None: preferred_mimetypes = kwargs["preferred_mimetypes"] else: preferred_mimetypes = Application.getInstance().getPreferences( ).getValue("gcode_filename_format/last_used_type") preferred_mimetype_list = preferred_mimetypes.split(";") 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)) file_types = [ft for ft in file_types if not ft["hide_in_file_dialog"]] if len(file_types) == 0: Logger.log("e", "There are no file types available to write with!") raise OutputDeviceError.WriteRequestFailedError( catalog.i18nc( "@info:warning", "There are no file types available to write with!")) preferred_mimetype = None for mime_type in preferred_mimetype_list: if any(ft["mime_type"] == mime_type for ft in file_types): preferred_mimetype = mime_type break 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 preferred_mimetype == item["mime_type"]: selected_filter = type_filter file_name = self.parseFilenameFormat(filename_format, file_name, application, global_stack) #file_name += self.filenameTackOn(print_setting) if file_name: file_name += "." + item["extension"] stored_directory = Application.getInstance().getPreferences().getValue( "gcode_filename_format/dialog_save_path") dialog.setDirectory(stored_directory) if file_name is not None: dialog.selectFile(file_name) dialog.setNameFilters(filters) if selected_filter is not None: dialog.selectNameFilter(selected_filter) if not dialog.exec_(): raise OutputDeviceError.UserCanceledError() save_path = dialog.directory().absolutePath() Application.getInstance().getPreferences().setValue( "gcode_filename_format/dialog_save_path", save_path) selected_type = file_types[filters.index(dialog.selectedNameFilter())] Application.getInstance().getPreferences().setValue( "gcode_filename_format/last_used_type", selected_type["mime_type"]) file_name = dialog.selectedFiles()[0] Logger.log("d", "Writing to [%s]..." % file_name) if os.path.exists(file_name): result = QMessageBox.question( None, catalog.i18nc("@title:window", "File Already Exists"), catalog.i18nc( "@label Don't translate the XML tag <filename>!", "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) 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") else: Logger.log("e", "Unrecognised OutputMode.") return None job = WriteFileJob(file_writer, stream, nodes, mode) job.setFileName(file_name) job.setAddToRecentFiles(True) job.progress.connect(self._onJobProgress) job.finished.connect(self._onWriteJobFinished) message = Message( catalog.i18nc( "@info:progress Don't translate the XML tags <filename>!", "Saving to <filename>{0}</filename>").format(file_name), 0, False, -1, catalog.i18nc("@info:title", "Saving")) message.show() job.setMessage(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 Don't translate the XML tags <filename>!", "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 Don't translate the XML tags <filename> or <message>!", "Could not save to <filename>{0}</filename>: <message>{1}</message>" ).format()) from e
def requestWrite(self, nodes, file_name = None, limit_mimetypes = None, file_handler = None, **kwargs): """Request the specified nodes to be written to a file. :param nodes: A collection of scene nodes that should be written to the file. :param file_name: A suggestion for the file name to write to. Can be freely ignored if providing a file name makes no sense. :param limit_mimetypes: Should we limit the available MIME types to the MIME types available to the currently active machine? :param kwargs: Keyword arguments. """ if self._writing: raise OutputDeviceError.DeviceBusyError() # Set up and display file dialog dialog = QFileDialog() dialog.setWindowTitle(catalog.i18nc("@title:window", "Save to Disk")) dialog.setFileMode(QFileDialog.FileMode.AnyFile) dialog.setAcceptMode(QFileDialog.AcceptMode.AcceptSave) # Ensure platform never ask for overwrite confirmation since we do this ourselves dialog.setOption(QFileDialog.Option.DontConfirmOverwrite) filters = [] mime_types = [] selected_filter = None if "preferred_mimetypes" in kwargs and kwargs["preferred_mimetypes"] is not None: preferred_mimetypes = kwargs["preferred_mimetypes"] else: preferred_mimetypes = Application.getInstance().getPreferences().getValue("local_file/last_used_type") preferred_mimetype_list = preferred_mimetypes.split(";") 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)) file_types = [ft for ft in file_types if not ft["hide_in_file_dialog"]] if len(file_types) == 0: Logger.log("e", "There are no file types available to write with!") raise OutputDeviceError.WriteRequestFailedError(catalog.i18nc("@info:warning", "There are no file types available to write with!")) # Find the first available preferred mime type preferred_mimetype = None for mime_type in preferred_mimetype_list: if any(ft["mime_type"] == mime_type for ft in file_types): preferred_mimetype = mime_type break extension_added = False 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 preferred_mimetype == item["mime_type"]: selected_filter = type_filter if file_name and not extension_added: extension_added = True file_name += "." + item["extension"] # CURA-6411: This code needs to be before dialog.selectFile and the filters, because otherwise in macOS (for some reason) the setDirectory call doesn't work. stored_directory = Application.getInstance().getPreferences().getValue("local_file/dialog_save_path") if stored_directory and stored_directory != "" and os.path.exists(stored_directory): dialog.setDirectory(stored_directory) # Add the file name before adding the extension to the dialog if file_name is not None: dialog.selectFile(file_name) dialog.setNameFilters(filters) if selected_filter is not None: dialog.selectNameFilter(selected_filter) if not dialog.exec(): raise OutputDeviceError.UserCanceledError() save_path = dialog.directory().absolutePath() Application.getInstance().getPreferences().setValue("local_file/dialog_save_path", save_path) selected_type = file_types[filters.index(dialog.selectedNameFilter())] Application.getInstance().getPreferences().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) if os.path.exists(file_name): result = QMessageBox.question(None, catalog.i18nc("@title:window", "File Already Exists"), catalog.i18nc("@label Don't translate the XML tag <filename>!", "The file <filename>{0}</filename> already exists. Are you sure you want to overwrite it?").format(file_name)) if result == QMessageBox.StandardButton.No: raise OutputDeviceError.UserCanceledError() # Actually writing file if file_handler: file_writer = file_handler.getWriter(selected_type["id"]) else: file_writer = Application.getInstance().getMeshFileHandler().getWriter(selected_type["id"]) if isinstance(file_writer, WorkspaceWriter): self.setLastOutputName(file_name) self.writeStarted.emit(self) 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") else: Logger.log("e", "Unrecognised OutputMode.") return None job = WriteFileJob(file_writer, stream, nodes, mode) job.setFileName(file_name) job.setAddToRecentFiles(True) # The file will be added into the "recent files" list upon success job.progress.connect(self._onJobProgress) job.finished.connect(self._onWriteJobFinished) message = Message(catalog.i18nc("@info:progress Don't translate the XML tags <filename>!", "Saving to <filename>{0}</filename>").format(file_name), 0, False, -1 , catalog.i18nc("@info:title", "Saving")) message.show() job.setMessage(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 Don't translate the XML tags <filename>!", "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 Don't translate the XML tags <filename> or <message>!", "Could not save to <filename>{0}</filename>: <message>{1}</message>").format(file_name, str(e))) from e
def requestWrite(self, nodes, file_name=None, limit_mimetypes=None, file_handler=None): if self._writing: raise OutputDeviceError.DeviceBusyError() 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"]) file_name = dialog.selectedFiles()[0] 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) 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
def requestWrite(self, nodes, file_name=None, filter_by_machine=False, file_handler=None, **kwargs): filter_by_machine = True # This plugin is intended to be used by machine (regardless of what it was told to do) if self._writing: raise OutputDeviceError.DeviceBusyError() # Formats supported by this application (File types that we can actually write) if file_handler: file_formats = file_handler.getSupportedFileTypesWrite() else: file_formats = Application.getInstance().getMeshFileHandler( ).getSupportedFileTypesWrite() if filter_by_machine: container = Application.getInstance().getGlobalContainerStack( ).findContainer({"file_formats": "*"}) # Create a list from supported file formats string machine_file_formats = [ file_type.strip() for file_type in container.getMetaDataEntry( "file_formats").split(";") ] # Take the intersection between file_formats and machine_file_formats. format_by_mimetype = { format["mime_type"]: format for format in file_formats } file_formats = [ format_by_mimetype[mimetype] for mimetype in machine_file_formats ] #Keep them ordered according to the preference in machine_file_formats. if len(file_formats) == 0: Logger.log("e", "There are no file formats available to write with!") raise OutputDeviceError.WriteRequestFailedError( catalog.i18nc( "@info:status", "There are no file formats available to write with!")) preferred_format = file_formats[0] # Just take the first file format available. if file_handler is not None: writer = file_handler.getWriterByMimeType( preferred_format["mime_type"]) else: writer = Application.getInstance().getMeshFileHandler( ).getWriterByMimeType(preferred_format["mime_type"]) extension = preferred_format["extension"] if file_name is None: file_name = self._automaticFileName(nodes) if extension: # Not empty string. extension = "." + extension file_name = os.path.join(self.getId(), os.path.splitext(file_name)[0] + extension) try: Logger.log("d", "Writing to %s", file_name) # Using buffering greatly reduces the write time for many lines of gcode if preferred_format["mode"] == FileWriter.OutputMode.TextMode: self._stream = open(file_name, "wt", buffering=1, encoding="utf-8") else: #Binary mode. self._stream = open(file_name, "wb", buffering=1) job = WriteFileJob(writer, self._stream, nodes, preferred_format["mode"]) job.setFileName(file_name) job.progress.connect(self._onProgress) job.finished.connect(self._onFinished) message = Message( catalog.i18nc( "@info:progress Don't translate the XML tags <filename>!", "Saving to Removable Drive <filename>{0}</filename>"). format(self.getName()), 0, False, -1, catalog.i18nc("@info:title", "Saving")) message.show() self.writeStarted.emit(self) job.setMessage(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 Don't translate the XML tags <filename> or <message>!", "Could not save to <filename>{0}</filename>: <message>{1}</message>" ).format(file_name, str(e))) 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 Don't translate the XML tags <filename> or <message>!", "Could not save to <filename>{0}</filename>: <message>{1}</message>" ).format(file_name, str(e))) from e
def requestWrite(self, nodes, file_name = None, filter_by_machine = False, file_handler = None, **kwargs): filter_by_machine = True # This plugin is indended to be used by machine (regardless of what it was told to do) if self._writing: raise OutputDeviceError.DeviceBusyError() # Formats supported by this application (File types that we can actually write) if file_handler: file_formats = file_handler.getSupportedFileTypesWrite() else: file_formats = Application.getInstance().getMeshFileHandler().getSupportedFileTypesWrite() if filter_by_machine: container = Application.getInstance().getGlobalContainerStack().findContainer({"file_formats": "*"}) # Create a list from supported file formats string machine_file_formats = [file_type.strip() for file_type in container.getMetaDataEntry("file_formats").split(";")] # Take the intersection between file_formats and machine_file_formats. file_formats = list(filter(lambda file_format: file_format["mime_type"] in machine_file_formats, file_formats)) if len(file_formats) == 0: Logger.log("e", "There are no file formats available to write with!") raise OutputDeviceError.WriteRequestFailedError(catalog.i18nc("There are no file formats available to write with!")) # Just take the first file format available. if file_handler is not None: writer = file_handler.getWriterByMimeType(file_formats[0]["mime_type"]) else: writer = Application.getInstance().getMeshFileHandler().getWriterByMimeType(file_formats[0]["mime_type"]) extension = file_formats[0]["extension"] if file_name is None: file_name = self._automaticFileName(nodes) if extension: # Not empty string. extension = "." + extension file_name = os.path.join(self.getId(), os.path.splitext(file_name)[0] + extension) try: Logger.log("d", "Writing to %s", file_name) # Using buffering greatly reduces the write time for many lines of gcode self._stream = open(file_name, "wt", buffering = 1, encoding = "utf-8") job = WriteFileJob(writer, self._stream, nodes, MeshWriter.OutputMode.TextMode) job.setFileName(file_name) job.progress.connect(self._onProgress) job.finished.connect(self._onFinished) message = Message(catalog.i18nc("@info:progress Don't translate the XML tags <filename>!", "Saving to Removable Drive <filename>{0}</filename>").format(self.getName()), 0, False, -1, catalog.i18nc("@info:title", "Saving")) message.show() self.writeStarted.emit(self) job.setMessage(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 Don't translate the XML tags <filename> or <message>!", "Could not save to <filename>{0}</filename>: <message>{1}</message>").format(file_name, str(e))) 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 Don't translate the XML tags <filename> or <message>!", "Could not save to <filename>{0}</filename>: <message>{1}</message>").format(file_name, str(e))) from e
def requestWrite(self, nodes, file_name=None, limit_mimetypes=None, file_handler=None, **kwargs): """Request the specified nodes to be written to a file. :param nodes: A collection of scene nodes that should be written to the file. :param file_name: A suggestion for the file name to write to. Can be freely ignored if providing a file name makes no sense. :param limit_mimetypes: Should we limit the available MIME types to the MIME types available to the currently active machine? :param kwargs: Keyword arguments. """ 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 if "preferred_mimetypes" in kwargs and kwargs[ "preferred_mimetypes"] is not None: preferred_mimetypes = kwargs["preferred_mimetypes"] else: preferred_mimetypes = Application.getInstance().getPreferences( ).getValue("local_file/last_used_type") preferred_mimetype_list = preferred_mimetypes.split(";") 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)) file_types = [ft for ft in file_types if not ft["hide_in_file_dialog"]] if len(file_types) == 0: Logger.log("e", "There are no file types available to write with!") raise OutputDeviceError.WriteRequestFailedError( catalog.i18nc( "@info:warning", "There are no file types available to write with!")) # Find the first available preferred mime type preferred_mimetype = None for mime_type in preferred_mimetype_list: if any(ft["mime_type"] == mime_type for ft in file_types): preferred_mimetype = mime_type break extension_added = False 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 preferred_mimetype == item["mime_type"]: selected_filter = type_filter if file_name and not extension_added: extension_added = True file_name += "." + item["extension"] # CURA-6411: This code needs to be before dialog.selectFile and the filters, because otherwise in macOS (for some reason) the setDirectory call doesn't work. stored_directory = Application.getInstance().getPreferences().getValue( "local_file/dialog_save_path") dialog.setDirectory(stored_directory) # Add the file name before adding the extension to the dialog if file_name is not None: dialog.selectFile(file_name) dialog.setNameFilters(filters) if selected_filter is not None: dialog.selectNameFilter(selected_filter) if not dialog.exec_(): raise OutputDeviceError.UserCanceledError() save_path = dialog.directory().absolutePath() Application.getInstance().getPreferences().setValue( "local_file/dialog_save_path", save_path) selected_type = file_types[filters.index(dialog.selectedNameFilter())] Application.getInstance().getPreferences().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) #file_name = file_name.replace('.gcode','.s3d') print(file_name) if os.path.exists(file_name): result = QMessageBox.question( None, catalog.i18nc("@title:window", "File Already Exists"), catalog.i18nc( "@label Don't translate the XML tag <filename>!", "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") else: Logger.log("e", "Unrecognised OutputMode.") return None #print("HELLO WRITE FILE") #print(file_writer) #print(stream) #print(nodes) #print(mode) #print("HELLO WRITE FILE DONE") job = WriteFileJob(file_writer, stream, nodes, mode) job.setFileName(file_name) job.setAddToRecentFiles( True ) # The file will be added into the "recent files" list upon success job.progress.connect(self._onJobProgress) job.finished.connect(self._onWriteJobFinished) save_name = file_name.replace('.gcode', '.s3d') message = Message( catalog.i18nc( "@info:progress Don't translate the XML tags <filename>!", "Saving to <filename>{0}</filename>").format(save_name), 0, False, -1, catalog.i18nc("@info:title", "Saving")) message.show() job.setMessage(message) self._writing = True import base64 from cryptography.hazmat.backends import default_backend from cryptography.hazmat.primitives import hashes from cryptography.hazmat.primitives.kdf.pbkdf2 import PBKDF2HMAC from cryptography.fernet import Fernet, InvalidToken key = b'fWn9BDrXryrtcxjXhaO2BR9Oc_bS_zk1k4b6aL_0rbI=' input_file = file_name if '.gcode' in file_name: output_file = file_name.replace('.gcode', '.s3d') else: output_file = file_name + '.s3d' #with open(input_file, 'rb') as f: # data = f.read() # Read the bytes of the input file #f.close() #print(data) fernet = Fernet(key) #encrypted = fernet.encrypt(data) #print(len(encrypted)) #with open(output_file, 'wb') as f: # f.write(encrypted) # Write the encrypted bytes to the output file job.start() with open(input_file, 'rb') as f: data = f.read() #print(data) encrypted = fernet.encrypt(data) with open(output_file, 'wb') as f: f.write(encrypted) #import os if os.path.exists(input_file): os.remove(input_file) # os.remove('/home/akshay/STLS/*') else: print("GCODE FILE MOVED OR TAMPERED WITH") 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 Don't translate the XML tags <filename>!", "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 Don't translate the XML tags <filename> or <message>!", "Could not save to <filename>{0}</filename>: <message>{1}</message>" ).format(file_name, str(e))) from e
def requestWrite(self, nodes, file_name = None, limit_mimetypes = None, file_handler = None, **kwargs): 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 if "preferred_mimetype" in kwargs and kwargs["preferred_mimetype"] is not None: preferred_mimetype = kwargs["preferred_mimetype"] else: preferred_mimetype = 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 preferred_mimetype == 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) 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") else: Logger.log("e", "Unrecognised OutputMode.") return None 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.setMessage(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
def requestWrite(self, nodes, file_name=None, limit_mimetypes=None, file_handler=None, **kwargs): filter_by_machine = True # This plugin is intended to be used by machine (regardless of what it was told to do) # Formats supported by this application (File types that we can actually write) if file_handler: file_formats = file_handler.getSupportedFileTypesWrite() else: file_formats = Application.getInstance().getMeshFileHandler( ).getSupportedFileTypesWrite() if filter_by_machine: container = Application.getInstance().getGlobalContainerStack( ).findContainer({"file_formats": "*"}) # Create a list from supported file formats string machine_file_formats = [ file_type.strip() for file_type in container.getMetaDataEntry( "file_formats").split(";") ] # Take the intersection between file_formats and machine_file_formats. format_by_mimetype = { format["mime_type"]: format for format in file_formats } file_formats = [ format_by_mimetype[mimetype] for mimetype in machine_file_formats ] #Keep them ordered according to the preference in machine_file_formats. if len(file_formats) == 0: Logger.log( "e", "Plugin Adv3: There are no file formats available to write with!" ) raise OutputDeviceError.WriteRequestFailedError( catalog.i18nc( "@info:status", "Plugin Adv3: There are no file formats available to write with!" )) preferred_format = file_formats[0] # Just take the first file format available. if file_handler is not None: file_handler = Application.getInstance().getMeshFileHandler() writer = file_handler.getWriterByMimeType( preferred_format["mime_type"]) extension = preferred_format["extension"] if file_name is None: file_name = self._automaticFileName(nodes) self.fileNoExt = file_name if extension: # Not empty string. #if extension == "gcode": # extension = "g" extension = "." + extension file_name = os.path.splitext(file_name)[0] + extension #For this example, we will write to a file in a fixed location. self.output_file_name = os.path.expanduser("~/" + file_name) file_stream = open(self.output_file_name, "w", encoding="utf-8") job = WriteFileJob( writer, file_stream, nodes, preferred_format["mode"] ) #We'll create a WriteFileJob, which gets run asynchronously in the background. #job.progress.connect(self._onProgress) #You can listen to the event for when it's done and when it's progressing. job.finished.connect( self._onFinished) #This way we can properly close the file stream. Logger.log("d", "Plugin Adv3: saveing file started...") job.start()
def requestWrite(self, nodes, file_name=None, limit_mimetypes=None, file_handler=None, **kwargs): if self._writing: raise OutputDeviceError.DeviceBusyError() # Set up and display file dialog dialog = QFileDialog() dialog.setWindowTitle(self._translations.get("save_file_window")) 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 if "preferred_mimetypes" in kwargs and kwargs[ "preferred_mimetypes"] is not None: preferred_mimetypes = kwargs["preferred_mimetypes"] else: preferred_mimetypes = Application.getInstance().getPreferences( ).getValue("local_file/last_used_type") preferred_mimetype_list = preferred_mimetypes.split(";") 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)) file_types = [ft for ft in file_types if not ft["hide_in_file_dialog"]] if len(file_types) == 0: Logger.log("e", "There are no file types available to write with!") raise OutputDeviceError.WriteRequestFailedError( self._translations.get("no_file_warning")) # Find the first available preferred mime type preferred_mimetype = None for mime_type in preferred_mimetype_list: if any(ft["mime_type"] == mime_type for ft in file_types): preferred_mimetype = mime_type break 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 preferred_mimetype == item["mime_type"]: selected_filter = type_filter if file_name: file_name += "." + item["extension"] # CURA-6411: This code needs to be before dialog.selectFile and the filters, because otherwise in macOS (for some reason) the setDirectory call doesn't work. stored_directory = Application.getInstance().getPreferences().getValue( "local_file/dialog_save_path") dialog.setDirectory(stored_directory) # Add the file name before adding the extension to the dialog if file_name is not None: dialog.selectFile(file_name) dialog.setNameFilters(filters) if selected_filter is not None: dialog.selectNameFilter(selected_filter) if not dialog.exec_(): raise OutputDeviceError.UserCanceledError() save_path = dialog.directory().absolutePath() Application.getInstance().getPreferences().setValue( "local_file/dialog_save_path", save_path) selected_type = file_types[filters.index(dialog.selectedNameFilter())] Application.getInstance().getPreferences().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) if os.path.exists(file_name): result = QMessageBox.question( None, self._translations.get("file_exists_window").format( file_name[file_name.rfind("/") + 1:]), self._translations.get("file_overwrite_label").format( file_name[file_name.rfind("/") + 1:])) 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") else: Logger.log("e", "Unrecognised OutputMode.") return None # Adding screeshot section screenshot_string = utils.add_screenshot() if screenshot_string != "": stream.write(screenshot_string) # End of screeshot section job = WriteFileJob(file_writer, stream, nodes, mode) job.setFileName(file_name) # The file will be added into the "recent files" list upon success job.setAddToRecentFiles(True) job.progress.connect(self._onJobProgress) job.finished.connect(self._onWriteJobFinished) message = Message( self._translations.get("file_saving_progress").format( file_name), 0, False, -1, self._translations.get("file_saving_title")) message.show() job.setMessage(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( self._translations.get("permission_denied").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( self._translations.get("permission_denied2").format( file_name, str(e))) from e