Esempio n. 1
0
    def requestWrite(self,
                     nodes,
                     file_name=None,
                     limit_mimetypes=None,
                     file_handler=None):
        if self._writing:
            raise OutputDeviceError.DeviceBusyError()
        scene = Application.getInstance().getController().getScene()
        gcode_list = getattr(scene, "gcode_list")  #get gcodes array of strings

        dialog = QFileDialog()
        spliter = False
        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"])

        if ".gcode" in file_name:
            resulte = QMessageBox.question(
                None, catalog.i18nc("@title:window", "Splitting this file"),
                catalog.i18nc(
                    "@label", "Splitting file <filename>{0}</filename> to " +
                    str(len(gcode_list)) + " part?").format(file_name))
            if resulte == QMessageBox.Yes:
                spliter = True

        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()

        if file_handler:
            file_writer = file_handler.getWriter(selected_type["id"])
        else:
            file_writer = Application.getInstance().getMeshFileHandler(
            ).getWriter(selected_type["id"])
        nodes.append(-10)  #important
        #QMessageBox.question(None, catalog.i18nc("@title:window", str(len(gcode_list)) ), catalog.i18nc("@label", "The file <filename>{0}</filename> already exists. Are you sure you want to overwrite it?").format(file_name))
        i = 0
        if spliter:
            for gcode in gcode_list:  #circle for layer
                try:
                    nodes[1] = i
                    file_name = dialog.selectedFiles()[0].replace(
                        ".gcode",
                        str(i) + ".gcode")
                    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)
                    if 0 == i:
                        job.progress.connect(self._onJobProgress)
                        job.finished.connect(self._onWriteJobFinished)
                    self._writing = True
                    job.start()
                    i = i + 1
                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
            if os.path.exists(file_name):
                os.remove(file_name)
        else:
            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()
                i = i + 1
            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
Esempio n. 2
0
    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
Esempio n. 3
0
    def requestWrite(self, node, file_name = None, filter_by_machine = False):
        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)
        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()

        # Just take the first file format available.
        writer = Application.getInstance().getMeshFileHandler().getWriterByMimeType(file_formats[0]["mime_type"])
        extension = file_formats[0]["extension"]

        if file_name is None:
            for n in BreadthFirstIterator(node):
                if n.getMeshData():
                    file_name = n.getName()
                    if file_name:
                        break

        if not file_name:
            Logger.log("e", "Could not determine a proper file name when trying to write to %s, aborting", self.getName())
            raise OutputDeviceError.WriteRequestFailedError()

        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)
            stream = open(file_name, "wt")
            job = WriteMeshJob(writer, stream, node, MeshWriter.OutputMode.TextMode)
            job.setFileName(file_name)
            job.progress.connect(self._onProgress)
            job.finished.connect(self._onFinished)

            message = Message(catalog.i18nc("@info:progress", "Saving to Removable Drive <filename>{0}</filename>").format(self.getName()), 0, False, -1)
            message.show()

            self.writeStarted.emit(self)

            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", "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", "Could not save to <filename>{0}</filename>: <message>{1}</message>").format(file_name, str(e))) from e
Esempio n. 4
0
    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.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")
        if stored_directory and 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.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.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
Esempio n. 5
0
    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(
                catalog.i18nc(
                    "@info:warning",
                    "There are no file types available to write with!"))

        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 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

            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 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
Esempio n. 6
0
    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
Esempio n. 7
0
    def requestWrite(self,
                     nodes: List[SceneNode],
                     file_name: Optional[str] = None,
                     limit_mimetypes: bool = False,
                     file_handler: Optional[FileHandler] = None,
                     **kwargs: str) -> None:
        self.writeStarted.emit(self)

        self.sendMaterialProfiles()

        # Formats supported by this application (file types that we can actually write).
        if file_handler:
            file_formats = file_handler.getSupportedFileTypesWrite()
        else:
            file_formats = CuraApplication.getInstance().getMeshFileHandler(
            ).getSupportedFileTypesWrite()

        global_stack = CuraApplication.getInstance().getGlobalContainerStack()
        # Create a list from the supported file formats string.
        if not global_stack:
            Logger.log("e", "Missing global stack!")
            return

        machine_file_formats = global_stack.getMetaDataEntry(
            "file_formats").split(";")
        machine_file_formats = [
            file_type.strip() for file_type in machine_file_formats
        ]
        # Exception for UM3 firmware version >=4.4: UFP is now supported and should be the preferred file format.
        if "application/x-ufp" not in machine_file_formats and Version(
                self.firmwareVersion) >= Version("4.4"):
            machine_file_formats = ["application/x-ufp"] + machine_file_formats

        # 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(
                i18n_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(
                cast(str, preferred_format["mime_type"]))
        else:
            writer = CuraApplication.getInstance().getMeshFileHandler(
            ).getWriterByMimeType(cast(str, preferred_format["mime_type"]))

        if not writer:
            Logger.log("e",
                       "Unexpected error when trying to get the FileWriter")
            return

        # This function pauses with the yield, waiting on instructions on which printer it needs to print with.
        if not writer:
            Logger.log("e", "Missing file or mesh writer!")
            return
        self._sending_job = self._sendPrintJob(writer, preferred_format, nodes)
        if self._sending_job is not None:
            self._sending_job.send(None)  # Start the generator.

            if len(self._printers) > 1:  # We need to ask the user.
                self._spawnPrinterSelectionDialog()
                is_job_sent = True
            else:  # Just immediately continue.
                self._sending_job.send("")  # No specifically selected printer.
                is_job_sent = self._sending_job.send(None)
    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
        last_used_type = self._preferences.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 = self._preferences.getValue(
            "local_file/dialog_save_path")
        dialog.setDirectory(stored_directory)

        if not dialog.exec_():
            raise OutputDeviceError.UserCanceledError()

        save_path = dialog.directory().absolutePath()
        self._preferences.setValue("local_file/dialog_save_path", save_path)

        selected_type = file_types[filters.index(dialog.selectedNameFilter())]
        self._preferences.setValue("local_file/last_used_type",
                                   selected_type["mime_type"])

        # Get file name from file dialog
        file_name = dialog.selectedFiles()[0]
        active_build_plate = Application.getInstance().getMultiBuildPlateModel(
        ).activeBuildPlate
        scene = Application.getInstance().getController().getScene()
        gcode_dict = getattr(scene, "gcode_dict", None)
        if not gcode_dict:
            return
        _gcode = gcode_dict.get(active_build_plate, None)
        self.save_gcode(file_name, _gcode)
Esempio n. 9
0
    def requestWrite(self, node, file_name=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")

        file_types = Application.getInstance().getMeshFileHandler(
        ).getSupportedFileTypesWrite()
        file_types.sort(key=lambda k: k["description"])

        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
                file_name += "." + item["extension"]

        dialog.setNameFilters(filters)
        if selected_filter != None:
            dialog.selectNameFilter(selected_filter)

        if file_name != None:
            dialog.selectFile(file_name)

        dialog.restoreState(Preferences.getInstance().getValue(
            "local_file/dialog_state").encode())

        if not dialog.exec_():
            raise OutputDeviceError.UserCanceledError()

        Preferences.getInstance().setValue("local_file/dialog_state",
                                           str(dialog.saveState()))

        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)
        mesh_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")
            elif mode == MeshWriter.OutputMode.BinaryMode:
                Logger.log("d", "Writing to Local File %s in binary mode",
                           file_name)
                stream = open(file_name, "wb")

            job = WriteMeshJob(mesh_writer, stream, node, 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
Esempio n. 10
0
    def requestWrite(self, node, file_name=None, filter_by_machine=False):
        if self._writing:
            raise OutputDeviceError.DeviceBusyError()

        self._writing = True

        # load settings
        if Preferences.getInstance().getValue("MPSelectMini/ip"):
            ip = Preferences.getInstance().getValue("MPSelectMini/ip")
        if Preferences.getInstance().getValue("MPSelectMini/start_print"):
            start_print = Preferences.getInstance().getValue(
                "MPSelectMini/start_print")

        try:
            start_print
        except NameError:
            start_print = False

        # check for valid ip
        if not ip:
            raise OutputDeviceError.WriteRequestFailedError(
                catalog.i18nc("@info:status", "Invalid IP"))

        # Get GCode
        file_formats = Application.getInstance().getMeshFileHandler(
        ).getSupportedFileTypesWrite()
        mesh_writer = Application.getInstance().getMeshFileHandler(
        ).getWriterByMimeType("text/x-gcode")
        stream = io.StringIO()

        mesh_writer.write(stream, node, MeshWriter.OutputMode.TextMode)
        gcode = stream.getvalue()

        try:
            # Upload GCode
            s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
            s.connect((ip, 80))
            s.send(bytes('POST /upload HTTP/1.1\r\n', 'ascii'))
            s.send(
                bytes(
                    'Content-Type: multipart/form-data; boundary=------------------------2d30fc993bb09c6a\r\n',
                    'ascii'))
            s.send(bytes('\r\n', 'ascii'))
            s.send(
                bytes('--------------------------2d30fc993bb09c6a\r\n',
                      'ascii'))
            s.send(
                bytes(
                    'Content-Disposition: form-data; name="filedata"; filename="cache.gc"\r\n',
                    'ascii'))
            s.send(bytes('Content-Type: application/octet-stream\r\n',
                         'ascii'))
            s.send(bytes('\r\n', 'ascii'))
            s.send(bytes(gcode, 'ascii'))
            s.send(bytes('\r\n', 'ascii'))
            s.send(
                bytes('--------------------------2d30fc993bb09c6a--\r\n',
                      'ascii'))
            response = str(s.recv(1024), 'ascii')
            s.close()

            # Check upload response
            if response.startswith('HTTP/1.1 200 OK'):
                message = Message(
                    catalog.i18nc("@info:status", "Upload Success"))
                message.show()
            else:
                Logger.log(
                    "e", "Invalid http response uploading gcode:\n" + response)
                raise OutputDeviceError.WriteRequestFailedError(
                    catalog.i18nc("@info:status", "Upload Failed"))

            # Send cancel print (prevents upload bug where printer will start before heating extruder)
            s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
            s.connect((ip, 80))
            s.send(bytes('GET /set?cmd={P:X} HTTP/1.1\r\n', 'ascii'))
            s.send(bytes('\r\n', 'ascii'))
            response = str(s.recv(1024), 'ascii')
            s.close()

            if start_print:
                # Send start print
                s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
                s.connect((ip, 80))
                s.send(bytes('GET /set?code=M565 HTTP/1.1\r\n', 'ascii'))
                s.send(bytes('\r\n', 'ascii'))
                response = str(s.recv(1024), 'ascii')
                s.close()

                # Check start print response
                if response.startswith('HTTP/1.1 200 OK'):
                    message = Message(
                        catalog.i18nc("@info:status",
                                      "<b>Printing Started</b>"))
                    message.show()
                else:
                    Logger.log(
                        "e", "Invalid http response starting print job:\n" +
                        response)
                    raise OutputDeviceError.WriteRequestFailedError(
                        catalog.i18nc("@info:status", "Start Print Failed"))

        except (TimeoutError):
            raise OutputDeviceError.WriteRequestFailedError(
                catalog.i18nc("@info:status", "Connection Timeout"))

        self._writing = False
    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