Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

CURA-12138 export for support option #970

Merged
merged 5 commits into from
Oct 7, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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
Loading