mirror of
https://github.com/Ultimaker/Cura.git
synced 2025-07-10 16:27:51 -06:00
re-implement requestWrite
This commit is contained in:
parent
529b483f36
commit
b90e5b3262
4 changed files with 92 additions and 262 deletions
|
@ -17,7 +17,6 @@ from cura.CuraApplication import CuraApplication
|
||||||
from cura.PrinterOutput.NetworkedPrinterOutputDevice import AuthState
|
from cura.PrinterOutput.NetworkedPrinterOutputDevice import AuthState
|
||||||
from cura.PrinterOutput.PrinterOutputDevice import ConnectionType
|
from cura.PrinterOutput.PrinterOutputDevice import ConnectionType
|
||||||
|
|
||||||
from .CloudProgressMessage import CloudProgressMessage
|
|
||||||
from .CloudApiClient import CloudApiClient
|
from .CloudApiClient import CloudApiClient
|
||||||
from ..UltimakerNetworkedPrinterOutputDevice import UltimakerNetworkedPrinterOutputDevice
|
from ..UltimakerNetworkedPrinterOutputDevice import UltimakerNetworkedPrinterOutputDevice
|
||||||
from ..MeshFormatHandler import MeshFormatHandler
|
from ..MeshFormatHandler import MeshFormatHandler
|
||||||
|
@ -84,15 +83,11 @@ class CloudOutputDevice(UltimakerNetworkedPrinterOutputDevice):
|
||||||
self._account = api_client.account
|
self._account = api_client.account
|
||||||
self._cluster = cluster
|
self._cluster = cluster
|
||||||
self.setAuthenticationState(AuthState.NotAuthenticated)
|
self.setAuthenticationState(AuthState.NotAuthenticated)
|
||||||
|
|
||||||
self._setInterfaceElements()
|
self._setInterfaceElements()
|
||||||
|
|
||||||
# Trigger the printersChanged signal when the private signal is triggered.
|
# Trigger the printersChanged signal when the private signal is triggered.
|
||||||
self.printersChanged.connect(self._clusterPrintersChanged)
|
self.printersChanged.connect(self._clusterPrintersChanged)
|
||||||
|
|
||||||
# We only allow a single upload at a time.
|
|
||||||
self._progress = CloudProgressMessage()
|
|
||||||
|
|
||||||
# Keep server string of the last generated time to avoid updating models more than once for the same response
|
# Keep server string of the last generated time to avoid updating models more than once for the same response
|
||||||
self._received_printers = None # type: Optional[List[ClusterPrinterStatus]]
|
self._received_printers = None # type: Optional[List[ClusterPrinterStatus]]
|
||||||
self._received_print_jobs = None # type: Optional[List[ClusterPrintJobStatus]]
|
self._received_print_jobs = None # type: Optional[List[ClusterPrintJobStatus]]
|
||||||
|
@ -143,15 +138,14 @@ class CloudOutputDevice(UltimakerNetworkedPrinterOutputDevice):
|
||||||
self.setConnectionText(I18N_CATALOG.i18nc("@info:status", "Connected via Cloud"))
|
self.setConnectionText(I18N_CATALOG.i18nc("@info:status", "Connected via Cloud"))
|
||||||
|
|
||||||
## Called when Cura requests an output device to receive a (G-code) file.
|
## Called when Cura requests an output device to receive a (G-code) file.
|
||||||
def requestWrite(self, nodes: List["SceneNode"], file_name: Optional[str] = None, limit_mimetypes: bool = False,
|
def requestWrite(self, nodes: List[SceneNode], file_name: Optional[str] = None, limit_mimetypes: bool = False,
|
||||||
file_handler: Optional["FileHandler"] = None, filter_by_machine: bool = False, **kwargs) -> None:
|
file_handler: Optional[FileHandler] = None, filter_by_machine: bool = False, **kwargs) -> None:
|
||||||
|
|
||||||
# Show an error message if we're already sending a job.
|
# Show an error message if we're already sending a job.
|
||||||
if self._progress.visible:
|
if self._progress.visible:
|
||||||
message = Message(
|
message = Message(
|
||||||
text=I18N_CATALOG.i18nc("@info:status",
|
text=I18N_CATALOG.i18nc("@info:status", "Please wait until the current job has been sent."),
|
||||||
"Sending new jobs (temporarily) blocked, still sending the previous print job."),
|
title=I18N_CATALOG.i18nc("@info:title", "Print error"),
|
||||||
title=I18N_CATALOG.i18nc("@info:title", "Cloud error"),
|
|
||||||
lifetime=10
|
lifetime=10
|
||||||
)
|
)
|
||||||
message.show()
|
message.show()
|
||||||
|
@ -170,8 +164,8 @@ class CloudOutputDevice(UltimakerNetworkedPrinterOutputDevice):
|
||||||
Logger.log("e", "Missing file or mesh writer!")
|
Logger.log("e", "Missing file or mesh writer!")
|
||||||
return self._onUploadError(I18N_CATALOG.i18nc("@info:status", "Could not export print job."))
|
return self._onUploadError(I18N_CATALOG.i18nc("@info:status", "Could not export print job."))
|
||||||
|
|
||||||
|
# TODO: use stream just like the network output device
|
||||||
mesh = mesh_format.getBytes(nodes)
|
mesh = mesh_format.getBytes(nodes)
|
||||||
|
|
||||||
self._tool_path = mesh
|
self._tool_path = mesh
|
||||||
request = CloudPrintJobUploadRequest(
|
request = CloudPrintJobUploadRequest(
|
||||||
job_name=file_name or mesh_format.file_extension,
|
job_name=file_name or mesh_format.file_extension,
|
||||||
|
@ -236,7 +230,6 @@ class CloudOutputDevice(UltimakerNetworkedPrinterOutputDevice):
|
||||||
## Shows a message when the upload has succeeded
|
## Shows a message when the upload has succeeded
|
||||||
# \param response: The response from the cloud API.
|
# \param response: The response from the cloud API.
|
||||||
def _onPrintUploadCompleted(self, response: CloudPrintResponse) -> None:
|
def _onPrintUploadCompleted(self, response: CloudPrintResponse) -> None:
|
||||||
Logger.log("d", "The cluster will be printing this print job with the ID %s", response.cluster_job_id)
|
|
||||||
self._progress.hide()
|
self._progress.hide()
|
||||||
Message(
|
Message(
|
||||||
text=I18N_CATALOG.i18nc("@info:status", "Print job was successfully sent to the printer."),
|
text=I18N_CATALOG.i18nc("@info:status", "Print job was successfully sent to the printer."),
|
||||||
|
|
|
@ -6,13 +6,17 @@ from PyQt5.QtGui import QDesktopServices
|
||||||
from PyQt5.QtCore import pyqtSlot, QUrl, pyqtSignal, pyqtProperty
|
from PyQt5.QtCore import pyqtSlot, QUrl, pyqtSignal, pyqtProperty
|
||||||
|
|
||||||
from UM.FileHandler.FileHandler import FileHandler
|
from UM.FileHandler.FileHandler import FileHandler
|
||||||
|
from UM.FileHandler.WriteFileJob import WriteFileJob
|
||||||
from UM.Logger import Logger
|
from UM.Logger import Logger
|
||||||
|
from UM.Message import Message
|
||||||
from UM.i18n import i18nCatalog
|
from UM.i18n import i18nCatalog
|
||||||
from UM.Scene.SceneNode import SceneNode
|
from UM.Scene.SceneNode import SceneNode
|
||||||
|
from cura.CuraApplication import CuraApplication
|
||||||
from cura.PrinterOutput.NetworkedPrinterOutputDevice import AuthState
|
from cura.PrinterOutput.NetworkedPrinterOutputDevice import AuthState
|
||||||
from cura.PrinterOutput.PrinterOutputDevice import ConnectionType
|
from cura.PrinterOutput.PrinterOutputDevice import ConnectionType
|
||||||
|
|
||||||
from .ClusterApiClient import ClusterApiClient
|
from .ClusterApiClient import ClusterApiClient
|
||||||
|
from ..MeshFormatHandler import MeshFormatHandler
|
||||||
from ..SendMaterialJob import SendMaterialJob
|
from ..SendMaterialJob import SendMaterialJob
|
||||||
from ..UltimakerNetworkedPrinterOutputDevice import UltimakerNetworkedPrinterOutputDevice
|
from ..UltimakerNetworkedPrinterOutputDevice import UltimakerNetworkedPrinterOutputDevice
|
||||||
|
|
||||||
|
@ -38,22 +42,9 @@ class NetworkOutputDevice(UltimakerNetworkedPrinterOutputDevice):
|
||||||
self._cluster_api = ClusterApiClient(address, on_error=self._onNetworkError)
|
self._cluster_api = ClusterApiClient(address, on_error=self._onNetworkError)
|
||||||
# We don't have authentication over local networking, so we're always authenticated.
|
# We don't have authentication over local networking, so we're always authenticated.
|
||||||
self.setAuthenticationState(AuthState.Authenticated)
|
self.setAuthenticationState(AuthState.Authenticated)
|
||||||
|
|
||||||
self._setInterfaceElements()
|
self._setInterfaceElements()
|
||||||
|
|
||||||
self._active_camera_url = QUrl() # type: QUrl
|
self._active_camera_url = QUrl() # type: QUrl
|
||||||
|
|
||||||
# self._number_of_extruders = 2
|
|
||||||
# self._dummy_lambdas = (
|
|
||||||
# "", {}, io.BytesIO()
|
|
||||||
# ) # type: Tuple[Optional[str], Dict[str, Union[str, int, bool]], Union[io.StringIO, io.BytesIO]]
|
|
||||||
# self._error_message = None # type: Optional[Message]
|
|
||||||
# self._write_job_progress_message = None # type: Optional[Message]
|
|
||||||
# self._progress_message = None # type: Optional[Message]
|
|
||||||
# self._printer_selection_dialog = None # type: QObject
|
|
||||||
# self._printer_uuid_to_unique_name_mapping = {} # type: Dict[str, str]
|
|
||||||
# self._finished_jobs = [] # type: List[UM3PrintJobOutputModel]
|
|
||||||
# self._sending_job = None
|
|
||||||
|
|
||||||
## Set all the interface elements and texts for this output device.
|
## Set all the interface elements and texts for this output device.
|
||||||
def _setInterfaceElements(self) -> None:
|
def _setInterfaceElements(self) -> None:
|
||||||
|
@ -123,189 +114,7 @@ class NetworkOutputDevice(UltimakerNetworkedPrinterOutputDevice):
|
||||||
job = SendMaterialJob(device=self)
|
job = SendMaterialJob(device=self)
|
||||||
job.run()
|
job.run()
|
||||||
|
|
||||||
|
# ## Callback for when preview image was downloaded from cluster.
|
||||||
|
|
||||||
# TODO FROM HERE
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
def requestWrite(self, nodes: List["SceneNode"], file_name: Optional[str] = None, limit_mimetypes: bool = False,
|
|
||||||
file_handler: Optional["FileHandler"] = None, filter_by_machine: bool = False, **kwargs) -> None:
|
|
||||||
pass
|
|
||||||
# self.writeStarted.emit(self)
|
|
||||||
#
|
|
||||||
# self.sendMaterialProfiles()
|
|
||||||
#
|
|
||||||
# mesh_format = MeshFormatHandler(file_handler, self.firmwareVersion)
|
|
||||||
#
|
|
||||||
# # This function pauses with the yield, waiting on instructions on which printer it needs to print with.
|
|
||||||
# if not mesh_format.is_valid:
|
|
||||||
# Logger.log("e", "Missing file or mesh writer!")
|
|
||||||
# return
|
|
||||||
# self._sending_job = self._sendPrintJob(mesh_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()
|
|
||||||
# else: # Just immediately continue.
|
|
||||||
# self._sending_job.send("") # No specifically selected printer.
|
|
||||||
# self._sending_job.send(None)
|
|
||||||
#
|
|
||||||
# def _spawnPrinterSelectionDialog(self):
|
|
||||||
# if self._printer_selection_dialog is None:
|
|
||||||
# if PluginRegistry.getInstance() is not None:
|
|
||||||
# path = os.path.join(
|
|
||||||
# PluginRegistry.getInstance().getPluginPath("UM3NetworkPrinting"),
|
|
||||||
# "resources", "qml", "PrintWindow.qml"
|
|
||||||
# )
|
|
||||||
# self._printer_selection_dialog = self._application.createQmlComponent(path, {"OutputDevice": self})
|
|
||||||
# if self._printer_selection_dialog is not None:
|
|
||||||
# self._printer_selection_dialog.show()
|
|
||||||
|
|
||||||
# ## Allows the user to choose a printer to print with from the printer
|
|
||||||
# # selection dialogue.
|
|
||||||
# # \param target_printer The name of the printer to target.
|
|
||||||
# @pyqtSlot(str)
|
|
||||||
# def selectPrinter(self, target_printer: str = "") -> None:
|
|
||||||
# if self._sending_job is not None:
|
|
||||||
# self._sending_job.send(target_printer)
|
|
||||||
|
|
||||||
# @pyqtSlot()
|
|
||||||
# def cancelPrintSelection(self) -> None:
|
|
||||||
# self._sending_gcode = False
|
|
||||||
|
|
||||||
# ## Greenlet to send a job to the printer over the network.
|
|
||||||
# #
|
|
||||||
# # This greenlet gets called asynchronously in requestWrite. It is a
|
|
||||||
# # greenlet in order to optionally wait for selectPrinter() to select a
|
|
||||||
# # printer.
|
|
||||||
# # The greenlet yields exactly three times: First time None,
|
|
||||||
# # \param mesh_format Object responsible for choosing the right kind of format to write with.
|
|
||||||
# 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 _sendPrintJobWaitOnWriteJobFinished(self, job: WriteFileJob) -> None:
|
|
||||||
# if self._write_job_progress_message:
|
|
||||||
# self._write_job_progress_message.hide()
|
|
||||||
#
|
|
||||||
# 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 = "",
|
|
||||||
# description = "")
|
|
||||||
# self._progress_message.actionTriggered.connect(self._progressMessageActionTriggered)
|
|
||||||
# self._progress_message.show()
|
|
||||||
# parts = []
|
|
||||||
#
|
|
||||||
# target_printer, preferred_format, stream = self._dummy_lambdas
|
|
||||||
#
|
|
||||||
# # 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 = self._application.getPrintInformation().jobName + "." + preferred_format["extension"]
|
|
||||||
#
|
|
||||||
# output = stream.getvalue() # Either str or bytes depending on the output mode.
|
|
||||||
# if isinstance(stream, io.StringIO):
|
|
||||||
# output = cast(str, output).encode("utf-8")
|
|
||||||
# output = cast(bytes, output)
|
|
||||||
#
|
|
||||||
# parts.append(self._createFormPart("name=\"file\"; filename=\"%s\"" % file_name, output))
|
|
||||||
#
|
|
||||||
# self._latest_reply_handler = self.postFormWithParts("print_jobs/", parts,
|
|
||||||
# on_finished = self._onPostPrintJobFinished,
|
|
||||||
# on_progress = self._onUploadPrintJobProgress)
|
|
||||||
|
|
||||||
# def _onPostPrintJobFinished(self, reply: QNetworkReply) -> None:
|
|
||||||
# if self._progress_message:
|
|
||||||
# self._progress_message.hide()
|
|
||||||
# self._compressing_gcode = False
|
|
||||||
# self._sending_gcode = False
|
|
||||||
|
|
||||||
# def _onUploadPrintJobProgress(self, bytes_sent: int, bytes_total: int) -> None:
|
|
||||||
# if bytes_total > 0:
|
|
||||||
# new_progress = bytes_sent / bytes_total * 100
|
|
||||||
# # Treat upload progress as response. Uploading can take more than 10 seconds, so if we don't, we can get
|
|
||||||
# # timeout responses if this happens.
|
|
||||||
# self._last_response_time = time()
|
|
||||||
# if self._progress_message is not None and new_progress != self._progress_message.getProgress():
|
|
||||||
# self._progress_message.show() # Ensure that the message is visible.
|
|
||||||
# self._progress_message.setProgress(bytes_sent / bytes_total * 100)
|
|
||||||
#
|
|
||||||
# # If successfully sent:
|
|
||||||
# if bytes_sent == bytes_total:
|
|
||||||
# # Show a confirmation to the user so they know the job was sucessful and provide the option to switch to
|
|
||||||
# # the monitor tab.
|
|
||||||
# self._success_message = Message(
|
|
||||||
# I18N_CATALOG.i18nc("@info:status", "Print job was successfully sent to the printer."),
|
|
||||||
# lifetime=5, dismissable=True,
|
|
||||||
# title=I18N_CATALOG.i18nc("@info:title", "Data Sent"))
|
|
||||||
# self._success_message.addAction("View", I18N_CATALOG.i18nc("@action:button", "View in Monitor"), icon = "",
|
|
||||||
# description="")
|
|
||||||
# self._success_message.actionTriggered.connect(self._successMessageActionTriggered)
|
|
||||||
# self._success_message.show()
|
|
||||||
# else:
|
|
||||||
# if self._progress_message is not None:
|
|
||||||
# self._progress_message.setProgress(0)
|
|
||||||
# self._progress_message.hide()
|
|
||||||
|
|
||||||
# def _progressMessageActionTriggered(self, message_id: Optional[str] = None, action_id: Optional[str] = None) -> None:
|
|
||||||
# if action_id == "Abort":
|
|
||||||
# Logger.log("d", "User aborted sending print to remote.")
|
|
||||||
# if self._progress_message is not None:
|
|
||||||
# self._progress_message.hide()
|
|
||||||
# self._compressing_gcode = False
|
|
||||||
# self._sending_gcode = False
|
|
||||||
# self._application.getController().setActiveStage("PrepareStage")
|
|
||||||
#
|
|
||||||
# # After compressing the sliced model Cura sends data to printer, to stop receiving updates from the request
|
|
||||||
# # the "reply" should be disconnected
|
|
||||||
# if self._latest_reply_handler:
|
|
||||||
# self._latest_reply_handler.disconnect()
|
|
||||||
# self._latest_reply_handler = None
|
|
||||||
|
|
||||||
# def _successMessageActionTriggered(self, message_id: Optional[str] = None, action_id: Optional[str] = None) -> None:
|
|
||||||
# if action_id == "View":
|
|
||||||
# self._application.getController().setActiveStage("MonitorStage")
|
|
||||||
|
|
||||||
# def _onGetPreviewImageFinished(self, reply: QNetworkReply) -> None:
|
# def _onGetPreviewImageFinished(self, reply: QNetworkReply) -> None:
|
||||||
# reply_url = reply.url().toString()
|
# reply_url = reply.url().toString()
|
||||||
#
|
#
|
||||||
|
@ -317,53 +126,77 @@ class NetworkOutputDevice(UltimakerNetworkedPrinterOutputDevice):
|
||||||
# image.loadFromData(reply.readAll())
|
# image.loadFromData(reply.readAll())
|
||||||
# print_job.updatePreviewImage(image)
|
# print_job.updatePreviewImage(image)
|
||||||
|
|
||||||
# def _createMaterialOutputModel(self, material_data: Dict[str, Any]) -> "MaterialOutputModel":
|
## Send a print job to the cluster.
|
||||||
# material_manager = self._application.getMaterialManager()
|
def requestWrite(self, nodes: List[SceneNode], file_name: Optional[str] = None, limit_mimetypes: bool = False,
|
||||||
# material_group_list = None
|
file_handler: Optional[FileHandler] = None, filter_by_machine: bool = False, **kwargs) -> None:
|
||||||
#
|
|
||||||
# # Avoid crashing if there is no "guid" field in the metadata
|
# Show an error message if we're already sending a job.
|
||||||
# material_guid = material_data.get("guid")
|
if self._progress.visible:
|
||||||
# if material_guid:
|
message = Message(
|
||||||
# material_group_list = material_manager.getMaterialGroupListByGUID(material_guid)
|
text=I18N_CATALOG.i18nc("@info:status", "Please wait until the current job has been sent."),
|
||||||
#
|
title=I18N_CATALOG.i18nc("@info:title", "Print error"),
|
||||||
# # This can happen if the connected machine has no material in one or more extruders (if GUID is empty), or the
|
lifetime=10
|
||||||
# # material is unknown to Cura, so we should return an "empty" or "unknown" material model.
|
)
|
||||||
# if material_group_list is None:
|
message.show()
|
||||||
# material_name = I18N_CATALOG.i18nc("@label:material", "Empty") if len(material_data.get("guid", "")) == 0 \
|
return
|
||||||
# else I18N_CATALOG.i18nc("@label:material", "Unknown")
|
|
||||||
#
|
self.writeStarted.emit(self)
|
||||||
# return MaterialOutputModel(guid = material_data.get("guid", ""),
|
|
||||||
# type = material_data.get("material", ""),
|
# Make sure the printer is aware of all new materials as the new print job might contain one.
|
||||||
# color = material_data.get("color", ""),
|
self.sendMaterialProfiles()
|
||||||
# brand = material_data.get("brand", ""),
|
|
||||||
# name = material_data.get("name", material_name)
|
# Detect the correct export format depending on printer type and firmware version.
|
||||||
# )
|
mesh_format = MeshFormatHandler(file_handler, self.firmwareVersion)
|
||||||
#
|
if not mesh_format.is_valid:
|
||||||
# # Sort the material groups by "is_read_only = True" first, and then the name alphabetically.
|
Logger.log("e", "Missing file or mesh writer!")
|
||||||
# read_only_material_group_list = list(filter(lambda x: x.is_read_only, material_group_list))
|
return self._onUploadError(I18N_CATALOG.i18nc("@info:status", "Could not export print job."))
|
||||||
# non_read_only_material_group_list = list(filter(lambda x: not x.is_read_only, material_group_list))
|
|
||||||
# material_group = None
|
# Determine the filename.
|
||||||
# if read_only_material_group_list:
|
job_name = CuraApplication.getInstance().getPrintInformation().jobName
|
||||||
# read_only_material_group_list = sorted(read_only_material_group_list, key = lambda x: x.name)
|
extension = mesh_format.preferred_format.get("extension", "")
|
||||||
# material_group = read_only_material_group_list[0]
|
file_name = f"{job_name}.{extension}"
|
||||||
# elif non_read_only_material_group_list:
|
|
||||||
# non_read_only_material_group_list = sorted(non_read_only_material_group_list, key = lambda x: x.name)
|
# Export the file.
|
||||||
# material_group = non_read_only_material_group_list[0]
|
stream = mesh_format.createStream()
|
||||||
#
|
job = WriteFileJob(mesh_format.writer, stream, nodes, mesh_format.file_mode)
|
||||||
# if material_group:
|
job.setFileName(file_name)
|
||||||
# container = material_group.root_material_node.getContainer()
|
job.finished.connect(self._onPrintJobCreated)
|
||||||
# color = container.getMetaDataEntry("color_code")
|
job.start()
|
||||||
# brand = container.getMetaDataEntry("brand")
|
|
||||||
# material_type = container.getMetaDataEntry("material")
|
## Handler for when the print job was created locally.
|
||||||
# name = container.getName()
|
# It can now be sent over the network.
|
||||||
# else:
|
def _onPrintJobCreated(self, job: WriteFileJob) -> None:
|
||||||
# Logger.log("w",
|
self._progress.show()
|
||||||
# "Unable to find material with guid {guid}. Using data as provided by cluster".format(
|
parts = []
|
||||||
# guid=material_data["guid"]))
|
parts.append(self._createFormPart("name=owner", bytes(self._getUserName(), "utf-8"), "text/plain"))
|
||||||
# color = material_data["color"]
|
output = job.getStream().getvalue()
|
||||||
# brand = material_data["brand"]
|
parts.append(self._createFormPart("name=\"file\"; filename=\"%s\"" % job.getFileName(), output))
|
||||||
# material_type = material_data["material"]
|
self.postFormWithParts("print_jobs/", parts, on_finished=self._onPrintUploadCompleted,
|
||||||
# name = I18N_CATALOG.i18nc("@label:material", "Empty") if material_data["material"] == "empty" \
|
on_progress=self._onPrintJobUploadProgress)
|
||||||
# else I18N_CATALOG.i18nc("@label:material", "Unknown")
|
|
||||||
# return MaterialOutputModel(guid = material_data["guid"], type = material_type,
|
## Handler for print job upload progress.
|
||||||
# brand = brand, color = color, name = name)
|
def _onPrintJobUploadProgress(self, bytes_sent: int, bytes_total: int) -> None:
|
||||||
|
percentage = (bytes_sent / bytes_total) if bytes_total else 0
|
||||||
|
self._progress.setProgress(percentage * 100)
|
||||||
|
self.writeProgress.emit()
|
||||||
|
|
||||||
|
## Handler for when the print job was fully uploaded to the cluster.
|
||||||
|
def _onPrintUploadCompleted(self) -> None:
|
||||||
|
self._progress.hide()
|
||||||
|
Message(
|
||||||
|
text=I18N_CATALOG.i18nc("@info:status", "Print job was successfully sent to the printer."),
|
||||||
|
title=I18N_CATALOG.i18nc("@info:title", "Data Sent"),
|
||||||
|
lifetime=5
|
||||||
|
).show()
|
||||||
|
self.writeFinished.emit()
|
||||||
|
|
||||||
|
## Displays the given message if uploading the mesh has failed
|
||||||
|
# \param message: The message to display.
|
||||||
|
def _onUploadError(self, message: str = None) -> None:
|
||||||
|
self._progress.hide()
|
||||||
|
Message(
|
||||||
|
text=message or I18N_CATALOG.i18nc("@info:text", "Could not upload the data to the printer."),
|
||||||
|
title=I18N_CATALOG.i18nc("@info:title", "Network error"),
|
||||||
|
lifetime=10
|
||||||
|
).show()
|
||||||
|
self.writeError.emit()
|
||||||
|
|
|
@ -8,11 +8,11 @@ I18N_CATALOG = i18nCatalog("cura")
|
||||||
|
|
||||||
|
|
||||||
## Class responsible for showing a progress message while a mesh is being uploaded to the cloud.
|
## Class responsible for showing a progress message while a mesh is being uploaded to the cloud.
|
||||||
class CloudProgressMessage(Message):
|
class PrintJobUploadProgressMessage(Message):
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
super().__init__(
|
super().__init__(
|
||||||
title = I18N_CATALOG.i18nc("@info:status", "Sending Print Job"),
|
title = I18N_CATALOG.i18nc("@info:status", "Sending Print Job"),
|
||||||
text = I18N_CATALOG.i18nc("@info:status", "Uploading via Ultimaker Cloud"),
|
text = I18N_CATALOG.i18nc("@info:status", "Uploading print job to printer."),
|
||||||
progress = -1,
|
progress = -1,
|
||||||
lifetime = 0,
|
lifetime = 0,
|
||||||
dismissable = False,
|
dismissable = False,
|
|
@ -14,6 +14,7 @@ from cura.PrinterOutput.PrinterOutputDevice import ConnectionType
|
||||||
|
|
||||||
from .Utils import formatTimeCompleted, formatDateCompleted
|
from .Utils import formatTimeCompleted, formatDateCompleted
|
||||||
from .ClusterOutputController import ClusterOutputController
|
from .ClusterOutputController import ClusterOutputController
|
||||||
|
from .PrintJobUploadProgressMessage import PrintJobUploadProgressMessage
|
||||||
from .Models.UM3PrintJobOutputModel import UM3PrintJobOutputModel
|
from .Models.UM3PrintJobOutputModel import UM3PrintJobOutputModel
|
||||||
from .Models.Http.ClusterPrinterStatus import ClusterPrinterStatus
|
from .Models.Http.ClusterPrinterStatus import ClusterPrinterStatus
|
||||||
from .Models.Http.ClusterPrintJobStatus import ClusterPrintJobStatus
|
from .Models.Http.ClusterPrintJobStatus import ClusterPrintJobStatus
|
||||||
|
@ -60,6 +61,9 @@ class UltimakerNetworkedPrinterOutputDevice(NetworkedPrinterOutputDevice):
|
||||||
# Load the Monitor UI elements.
|
# Load the Monitor UI elements.
|
||||||
self._loadMonitorTab()
|
self._loadMonitorTab()
|
||||||
|
|
||||||
|
# The job upload progress message modal.
|
||||||
|
self._progress = PrintJobUploadProgressMessage()
|
||||||
|
|
||||||
## The IP address of the printer.
|
## The IP address of the printer.
|
||||||
@pyqtProperty(str, constant=True)
|
@pyqtProperty(str, constant=True)
|
||||||
def address(self) -> str:
|
def address(self) -> str:
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue