mirror of
https://github.com/Ultimaker/Cura.git
synced 2025-07-07 15:07:28 -06:00
Add upload messages for UI feedback, needs some refactoring
This commit is contained in:
parent
08e1b4691b
commit
5fdff17782
3 changed files with 76 additions and 28 deletions
|
@ -180,13 +180,16 @@ class NetworkedPrinterOutputDevice(PrinterOutputDevice):
|
||||||
self._createNetworkManager()
|
self._createNetworkManager()
|
||||||
assert (self._manager is not None)
|
assert (self._manager is not None)
|
||||||
|
|
||||||
def put(self, target: str, data: Union[str, bytes], on_finished: Optional[Callable[[QNetworkReply], None]]) -> None:
|
def put(self, target: str, data: Union[str, bytes], on_finished: Optional[Callable[[QNetworkReply], None]],
|
||||||
|
on_progress: Optional[Callable] = None) -> None:
|
||||||
self._validateManager()
|
self._validateManager()
|
||||||
request = self._createEmptyRequest(target)
|
request = self._createEmptyRequest(target)
|
||||||
self._last_request_time = time()
|
self._last_request_time = time()
|
||||||
if self._manager is not None:
|
if self._manager is not None:
|
||||||
reply = self._manager.put(request, data if isinstance(data, bytes) else data.encode())
|
reply = self._manager.put(request, data if isinstance(data, bytes) else data.encode())
|
||||||
self._registerOnFinishedCallback(reply, on_finished)
|
self._registerOnFinishedCallback(reply, on_finished)
|
||||||
|
if on_progress is not None:
|
||||||
|
reply.uploadProgress.connect(on_progress)
|
||||||
else:
|
else:
|
||||||
Logger.log("e", "Could not find manager.")
|
Logger.log("e", "Could not find manager.")
|
||||||
|
|
||||||
|
|
|
@ -72,6 +72,10 @@ class CloudOutputDevice(NetworkedPrinterOutputDevice):
|
||||||
self._print_jobs = [] # type: List[UM3PrintJobOutputModel]
|
self._print_jobs = [] # type: List[UM3PrintJobOutputModel]
|
||||||
self._number_of_extruders = 2 # All networked printers are dual-extrusion Ultimaker machines.
|
self._number_of_extruders = 2 # All networked printers are dual-extrusion Ultimaker machines.
|
||||||
|
|
||||||
|
# We only allow a single upload at a time.
|
||||||
|
self._sending_job = False
|
||||||
|
self._progress_message = None # type: Optional[Message]
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def _parseReply(reply: QNetworkReply) -> Tuple[int, Union[None, str, bytes]]:
|
def _parseReply(reply: QNetworkReply) -> Tuple[int, Union[None, str, bytes]]:
|
||||||
"""
|
"""
|
||||||
|
@ -117,14 +121,22 @@ class CloudOutputDevice(NetworkedPrinterOutputDevice):
|
||||||
## 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_mime_types: bool = False,
|
def requestWrite(self, nodes: List[SceneNode], file_name: Optional[str] = None, limit_mime_types: bool = False,
|
||||||
file_handler: Optional[FileHandler] = None, **kwargs: str) -> None:
|
file_handler: Optional[FileHandler] = None, **kwargs: str) -> None:
|
||||||
|
|
||||||
|
# Show an error message if we're already sending a job.
|
||||||
|
if self._sending_job:
|
||||||
|
self._onUploadError(self.I18N_CATALOG.i18nc(
|
||||||
|
"@info:status", "Sending new jobs (temporarily) blocked, still sending the previous print job."))
|
||||||
|
return
|
||||||
|
|
||||||
|
# Indicate we have started sending a job.
|
||||||
|
self._sending_job = True
|
||||||
self.writeStarted.emit(self)
|
self.writeStarted.emit(self)
|
||||||
|
|
||||||
file_format = self._determineFileFormat(file_handler)
|
file_format = self._determineFileFormat(file_handler)
|
||||||
writer = self._determineWriter(file_handler, file_format)
|
writer = self._determineWriter(file_handler, file_format)
|
||||||
|
|
||||||
# This function pauses with the yield, waiting on instructions on which printer it needs to print with.
|
|
||||||
if not writer:
|
if not writer:
|
||||||
Logger.log("e", "Missing file or mesh writer!")
|
Logger.log("e", "Missing file or mesh writer!")
|
||||||
|
self._onUploadError(self.I18N_CATALOG.i18nc("@info:status", "Could not export print job."))
|
||||||
return
|
return
|
||||||
|
|
||||||
stream = io.StringIO() if file_format["mode"] == FileWriter.OutputMode.TextMode else io.BytesIO()
|
stream = io.StringIO() if file_format["mode"] == FileWriter.OutputMode.TextMode else io.BytesIO()
|
||||||
|
@ -186,11 +198,12 @@ class CloudOutputDevice(NetworkedPrinterOutputDevice):
|
||||||
def printers(self):
|
def printers(self):
|
||||||
return self._printers
|
return self._printers
|
||||||
|
|
||||||
|
## Get remote print jobs.
|
||||||
@pyqtProperty("QVariantList", notify = printJobsChanged)
|
@pyqtProperty("QVariantList", notify = printJobsChanged)
|
||||||
def printJobs(self)-> List[UM3PrintJobOutputModel]:
|
def printJobs(self)-> List[UM3PrintJobOutputModel]:
|
||||||
return self._print_jobs
|
return self._print_jobs
|
||||||
|
|
||||||
## Get remote print jobs.
|
## Get remote print jobs that are still in the print queue.
|
||||||
@pyqtProperty("QVariantList", notify = printJobsChanged)
|
@pyqtProperty("QVariantList", notify = printJobsChanged)
|
||||||
def queuedPrintJobs(self) -> List[UM3PrintJobOutputModel]:
|
def queuedPrintJobs(self) -> List[UM3PrintJobOutputModel]:
|
||||||
return [print_job for print_job in self._print_jobs
|
return [print_job for print_job in self._print_jobs
|
||||||
|
@ -354,24 +367,27 @@ class CloudOutputDevice(NetworkedPrinterOutputDevice):
|
||||||
def _onPrintJobCreated(self, mesh: bytes, reply: QNetworkReply) -> None:
|
def _onPrintJobCreated(self, mesh: bytes, reply: QNetworkReply) -> None:
|
||||||
status_code, response = self._parseReply(reply)
|
status_code, response = self._parseReply(reply)
|
||||||
if status_code > 204 or not isinstance(response, dict) or "data" not in response:
|
if status_code > 204 or not isinstance(response, dict) or "data" not in response:
|
||||||
Logger.log("w", "Got unexpected response while trying to add print job to cluster: {}, {}"
|
Logger.log("w", "Unexpected response while adding to queue: {}, {}".format(status_code, response))
|
||||||
.format(status_code, response))
|
self._onUploadError(self.I18N_CATALOG.i18nc("@info:status", "Could not add print job to queue."))
|
||||||
self.writeError.emit()
|
|
||||||
return
|
return
|
||||||
|
|
||||||
# TODO: add progress messages so we have visual feedback when uploading to cloud
|
|
||||||
# TODO: Multipart upload
|
# TODO: Multipart upload
|
||||||
job_response = JobUploadResponse(**response.get("data"))
|
job_response = JobUploadResponse(**response.get("data"))
|
||||||
Logger.log("i", "Print job created successfully: %s", job_response.__dict__)
|
Logger.log("i", "Print job created successfully: %s", job_response.__dict__)
|
||||||
self.put(job_response.upload_url, data=mesh,
|
self.put(job_response.upload_url, data=mesh,
|
||||||
on_finished=lambda r: self._onPrintJobUploaded(job_response.job_id, r))
|
on_finished=lambda r: self._onPrintJobUploaded(job_response.job_id, r),
|
||||||
|
on_progress = self._onUploadPrintJobProgress)
|
||||||
|
|
||||||
|
def _onUploadPrintJobProgress(self, bytes_sent: int, bytes_total: int) -> None:
|
||||||
|
if bytes_total > 0:
|
||||||
|
self._updateUploadProgress(int((bytes_sent / bytes_total) * 100))
|
||||||
|
|
||||||
def _onPrintJobUploaded(self, job_id: str, reply: QNetworkReply) -> None:
|
def _onPrintJobUploaded(self, job_id: str, reply: QNetworkReply) -> None:
|
||||||
status_code = reply.attribute(QNetworkRequest.HttpStatusCodeAttribute)
|
status_code = reply.attribute(QNetworkRequest.HttpStatusCodeAttribute)
|
||||||
if status_code > 204:
|
if status_code > 204:
|
||||||
Logger.logException("w", "Received unexpected response from the job upload: %s, %s.", status_code,
|
Logger.log("w", "Received unexpected response from the job upload: %s, %s.", status_code,
|
||||||
bytes(reply.readAll()).decode())
|
bytes(reply.readAll()).decode())
|
||||||
self.writeError.emit()
|
self._onUploadError(self.I18N_CATALOG.i18nc("@info:status", "Could not add print job to queue."))
|
||||||
return
|
return
|
||||||
|
|
||||||
Logger.log("i", "Print job uploaded successfully: %s", reply.readAll())
|
Logger.log("i", "Print job uploaded successfully: %s", reply.readAll())
|
||||||
|
@ -381,25 +397,53 @@ class CloudOutputDevice(NetworkedPrinterOutputDevice):
|
||||||
def _onPrintJobRequested(self, reply: QNetworkReply) -> None:
|
def _onPrintJobRequested(self, reply: QNetworkReply) -> None:
|
||||||
status_code, response = self._parseReply(reply)
|
status_code, response = self._parseReply(reply)
|
||||||
if status_code > 204 or not isinstance(response, dict) or "data" not in response:
|
if status_code > 204 or not isinstance(response, dict) or "data" not in response:
|
||||||
Logger.log("w", "Got unexpected response while trying to request printing: %s, %s",
|
Logger.log("w", "Got unexpected response while trying to request printing: %s, %s", status_code, response)
|
||||||
status_code, response)
|
self._onUploadError(self.I18N_CATALOG.i18nc("@info:status", "Could not add print job to queue."))
|
||||||
self.writeError.emit()
|
|
||||||
return
|
return
|
||||||
|
|
||||||
print_response = PrintResponse(**response["data"])
|
print_response = PrintResponse(**response["data"])
|
||||||
Logger.log("i", "Print job requested successfully: %s", print_response.__dict__)
|
Logger.log("i", "Print job requested successfully: %s", print_response.__dict__)
|
||||||
self.writeFinished.emit()
|
self._onUploadSuccess()
|
||||||
|
|
||||||
def _showUploadErrorMessage(self):
|
def _updateUploadProgress(self, progress: int):
|
||||||
message = Message(self.I18N_CATALOG.i18nc(
|
if not self._progress_message:
|
||||||
"@info:status", "Sending new jobs (temporarily) blocked, still sending the previous print job."))
|
self._progress_message = Message(
|
||||||
|
text = self.I18N_CATALOG.i18nc("@info:status", "Sending data to remote cluster"),
|
||||||
|
title = self.I18N_CATALOG.i18nc("@info:title", "Sending Data..."),
|
||||||
|
progress = -1,
|
||||||
|
lifetime = 0,
|
||||||
|
dismissable = False,
|
||||||
|
use_inactivity_timer = False
|
||||||
|
)
|
||||||
|
self._progress_message.setProgress(progress)
|
||||||
|
self._progress_message.show()
|
||||||
|
|
||||||
|
def _resetUploadProgress(self):
|
||||||
|
if self._progress_message:
|
||||||
|
self._progress_message.hide()
|
||||||
|
self._progress_message = None
|
||||||
|
|
||||||
|
def _onUploadError(self, message: str = None):
|
||||||
|
self._resetUploadProgress()
|
||||||
|
if message:
|
||||||
|
message = Message(
|
||||||
|
text = message,
|
||||||
|
title = self.I18N_CATALOG.i18nc("@info:title", "Error"),
|
||||||
|
lifetime = 10,
|
||||||
|
dismissable = True
|
||||||
|
)
|
||||||
message.show()
|
message.show()
|
||||||
|
self._sending_job = False # the upload has failed so we're not sending a job anymore
|
||||||
|
self.writeError.emit()
|
||||||
|
|
||||||
def _showOrUpdateUploadProgressMessage(self, new_progress = 0):
|
def _onUploadSuccess(self):
|
||||||
# TODO: implement this
|
self._resetUploadProgress()
|
||||||
# See ClusterUM3OutputDevice for inspiration
|
message = Message(
|
||||||
pass
|
text = self.I18N_CATALOG.i18nc("@info:status", "Print job was successfully sent to the printer."),
|
||||||
|
title = self.I18N_CATALOG.i18nc("@info:title", "Data Sent"),
|
||||||
def _showUploadSuccessMessage(self):
|
lifetime = 5,
|
||||||
# TODO: implement this
|
dismissable = True,
|
||||||
pass
|
)
|
||||||
|
message.show()
|
||||||
|
self._sending_job = False # the upload has finished so we're not sending a job anymore
|
||||||
|
self.writeFinished.emit()
|
||||||
|
|
|
@ -120,6 +120,7 @@ class JobUploadResponse(BaseModel):
|
||||||
self.slicing_details = None # type: str
|
self.slicing_details = None # type: str
|
||||||
self.status = None # type: str
|
self.status = None # type: str
|
||||||
self.upload_url = None # type: str
|
self.upload_url = None # type: str
|
||||||
|
self.content_type = None # type: str
|
||||||
super().__init__(**kwargs)
|
super().__init__(**kwargs)
|
||||||
|
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue