Skip to content

Commit

Permalink
Merge pull request #970 from Ultimaker/CURA-12138-Export_for_support_…
Browse files Browse the repository at this point in the history
…option

CURA-12138 export for support option
  • Loading branch information
HellAholic authored Oct 7, 2024
2 parents 30d1f94 + d3d2ac9 commit 1b54414
Show file tree
Hide file tree
Showing 5 changed files with 46 additions and 10 deletions.
8 changes: 5 additions & 3 deletions UM/FileHandler/WriteFileJob.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
import io
import time

from typing import Any, Optional, Union
from typing import Any, Optional, Union, Dict


class WriteFileJob(Job):
Expand All @@ -19,13 +19,14 @@ class WriteFileJob(Job):
The writer defines what the result of this job is.
"""

def __init__(self, writer: Optional[FileWriter], stream: Union[io.BytesIO, io.StringIO], data: Any, mode: int) -> None:
def __init__(self, writer: Optional[FileWriter], stream: Union[io.BytesIO, io.StringIO], data: Any, mode: int, writer_args: Optional[Dict[str, Any]] = None) -> None:
"""Creates a new job for writing.
:param writer: The file writer to use, with the correct MIME type.
:param stream: The output stream to write to.
:param data: Whatever it is what we want to write.
:param mode: Additional information to send to the writer, for example: such as whether to
:param writer_args: Extra arguments to be passed to the writer
write in binary format or in ASCII format.
"""

Expand All @@ -37,6 +38,7 @@ def __init__(self, writer: Optional[FileWriter], stream: Union[io.BytesIO, io.St
self._mode = mode
self._add_to_recent_files = False # If this file should be added to the "recent files" list upon success
self._message = None # type: Optional[Message]
self._writer_args = writer_args if writer_args is not None else {}
self.progress.connect(self._onProgress)
self.finished.connect(self._onFinished)

Expand Down Expand Up @@ -73,7 +75,7 @@ def getAddToRecentFiles(self) -> bool:
def run(self) -> None:
Job.yieldThread()
begin_time = time.time()
self.setResult(None if not self._writer else self._writer.write(self._stream, self._data, self._mode))
self.setResult(None if not self._writer else self._writer.write(self._stream, self._data, self._mode, **self._writer_args))
if not self.getResult():
self.setError(Exception("No writer in WriteFileJob" if not self._writer else self._writer.getInformation()))
end_time = time.time()
Expand Down
12 changes: 11 additions & 1 deletion UM/Qt/Bindings/OutputDeviceManagerProxy.py
Original file line number Diff line number Diff line change
Expand Up @@ -89,10 +89,20 @@ def requestWriteToDevice(self, device_id: str, file_name: str, kwargs: Mapping[s
limit_mimetypes = kwargs.get("limit_mimetypes", None)
file_type = kwargs.get("file_type", "mesh")
preferred_mimetypes = kwargs.get("preferred_mimetypes", None)
silent_save = kwargs.get("silent_save", False)
writer_args = kwargs.get("writer_args", {})
# On Windows, calling requestWrite() on LocalFileOutputDevice crashes when called from a signal
# handler attached to a QML MenuItem. So instead, defer the call to the next run of the event
# loop, since that does work.
Application.getInstance().callLater(self._writeToDevice, [Application.getInstance().getController().getScene().getRoot()], device_id, file_name, limit_mimetypes, file_type, preferred_mimetypes = preferred_mimetypes)
Application.getInstance().callLater(self._writeToDevice,
[Application.getInstance().getController().getScene().getRoot()],
device_id,
file_name,
limit_mimetypes,
file_type,
preferred_mimetypes = preferred_mimetypes,
silent_save = silent_save,
writer_args = writer_args)

@pyqtSlot(str, str, "QVariantMap")
def requestWriteSelectionToDevice(self, device_id: str, file_name: str, kwargs: Mapping[str, str]) -> None:
Expand Down
2 changes: 1 addition & 1 deletion UM/Workspace/WorkspaceWriter.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,5 +8,5 @@ class WorkspaceWriter(FileWriter):
def __init__(self, add_to_recent_files: bool = True) -> None:
super().__init__(add_to_recent_files)

def write(self, stream, node, mode = FileWriter.OutputMode.BinaryMode):
def write(self, stream, node, mode = FileWriter.OutputMode.BinaryMode, **kwargs):
raise NotImplementedError("WorkspaceWriter plugin was not correctly implemented, no write was specified")
18 changes: 18 additions & 0 deletions plugins/FileLogger/FileLogger.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@
import logging.handlers
from typing import Set

from logging import StreamHandler, FileHandler

from UM.Logger import LogOutput
from UM.Resources import Resources
from UM.VersionUpgradeManager import VersionUpgradeManager
Expand Down Expand Up @@ -34,6 +36,22 @@ def setFileName(self, file_name: str) -> None:
else:
pass # TODO, add handling

def flush(self) -> None:
"""Flushes all the open output streams"""
for handler in self._logger.handlers:
if isinstance(handler, StreamHandler):
handler.flush()

def getFilesPaths(self) -> list[str]:
"""Gets the list of paths to files currently open for log writing"""
files_paths = []

for handler in self._logger.handlers:
if isinstance(handler, FileHandler):
files_paths.append(handler.baseFilename)

return files_paths

def log(self, log_type: str, message: str) -> None:
"""Log message to file.
Expand Down
16 changes: 11 additions & 5 deletions plugins/LocalFileOutputDevice/LocalFileOutputDevice.py
Original file line number Diff line number Diff line change
Expand Up @@ -136,16 +136,21 @@ def requestWrite(self, nodes, file_name = None, limit_mimetypes = None, file_han
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()
self._performWrite(file_name, selected_type, file_handler, nodes)

def _performWrite(self, file_name, selected_type, file_handler, nodes):
silent_save = kwargs.get("silent_save", False)
writer_args = kwargs.get("writer_args", {})
self._performWrite(file_name, selected_type, file_handler, nodes, silent_save, writer_args)

def _performWrite(self, file_name, selected_type, file_handler, nodes, silent_save, writer_args):
"""Writes the specified nodes to a file. This is split from requestWrite to allow interception
in other plugins. See Ultimaker/Cura#10917.
:param file_name: File path to write to.
:param selected_type: Selected file type to write.
:param file_handler: File handler for writing to the file.
:param nodes: A collection of scene nodes that should be written to the
:param silent_save: When true, ignore all side effects (set project name, add recent file, ...)
:param writer_args: Extra list of arguments to be given to the writer
file.
"""

Expand All @@ -155,7 +160,7 @@ def _performWrite(self, file_name, selected_type, file_handler, nodes):
else:
file_writer = Application.getInstance().getMeshFileHandler().getWriter(selected_type["id"])

if isinstance(file_writer, WorkspaceWriter):
if isinstance(file_writer, WorkspaceWriter) and not silent_save:
self.setLastOutputName(file_name)
self.writeStarted.emit(self)

Expand All @@ -171,9 +176,10 @@ def _performWrite(self, file_name, selected_type, file_handler, nodes):
Logger.log("e", "Unrecognised OutputMode.")
return None

job = WriteFileJob(file_writer, stream, nodes, mode)
job = WriteFileJob(file_writer, stream, nodes, mode, writer_args)
job.setFileName(file_name)
job.setAddToRecentFiles(True) # The file will be added into the "recent files" list upon success
if not silent_save:
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)

Expand Down

0 comments on commit 1b54414

Please sign in to comment.