diff --git a/plugins/UM3NetworkPrinting/src/Models/Http/ClusterPrintJobStatus.py b/plugins/UM3NetworkPrinting/src/Models/Http/ClusterPrintJobStatus.py index 86bf02f9dd..ea2adf4b1b 100644 --- a/plugins/UM3NetworkPrinting/src/Models/Http/ClusterPrintJobStatus.py +++ b/plugins/UM3NetworkPrinting/src/Models/Http/ClusterPrintJobStatus.py @@ -2,6 +2,8 @@ # Cura is released under the terms of the LGPLv3 or higher. from typing import List, Optional, Union, Dict, Any +from PyQt5.QtCore import QUrl + from cura.PrinterOutput.Models.PrinterConfigurationModel import PrinterConfigurationModel from .ClusterBuildPlate import ClusterBuildPlate diff --git a/plugins/UM3NetworkPrinting/src/Models/Http/ClusterPrinterStatus.py b/plugins/UM3NetworkPrinting/src/Models/Http/ClusterPrinterStatus.py index dcdca5a017..ad5d117ded 100644 --- a/plugins/UM3NetworkPrinting/src/Models/Http/ClusterPrinterStatus.py +++ b/plugins/UM3NetworkPrinting/src/Models/Http/ClusterPrinterStatus.py @@ -6,6 +6,7 @@ from PyQt5.QtCore import QUrl from cura.PrinterOutput.PrinterOutputController import PrinterOutputController from cura.PrinterOutput.Models.PrinterOutputModel import PrinterOutputModel + from .ClusterBuildPlate import ClusterBuildPlate from .ClusterPrintCoreConfiguration import ClusterPrintCoreConfiguration from ..BaseModel import BaseModel diff --git a/plugins/UM3NetworkPrinting/src/Models/UM3PrintJobOutputModel.py b/plugins/UM3NetworkPrinting/src/Models/UM3PrintJobOutputModel.py index 1a27fc3f73..a9099a21aa 100644 --- a/plugins/UM3NetworkPrinting/src/Models/UM3PrintJobOutputModel.py +++ b/plugins/UM3NetworkPrinting/src/Models/UM3PrintJobOutputModel.py @@ -3,6 +3,7 @@ from typing import List from PyQt5.QtCore import pyqtProperty, pyqtSignal +from PyQt5.QtGui import QImage from cura.PrinterOutput.Models.PrintJobOutputModel import PrintJobOutputModel from cura.PrinterOutput.PrinterOutputController import PrinterOutputController @@ -26,3 +27,8 @@ class UM3PrintJobOutputModel(PrintJobOutputModel): return self._configuration_changes = changes self.configurationChangesChanged.emit() + + def updatePreviewImageData(self, data: bytes) -> None: + image = QImage() + image.loadFromData(data) + self.updatePreviewImage(image) diff --git a/plugins/UM3NetworkPrinting/src/Network/ClusterApiClient.py b/plugins/UM3NetworkPrinting/src/Network/ClusterApiClient.py index df0dcad527..d3a3e61367 100644 --- a/plugins/UM3NetworkPrinting/src/Network/ClusterApiClient.py +++ b/plugins/UM3NetworkPrinting/src/Network/ClusterApiClient.py @@ -76,6 +76,12 @@ class ClusterApiClient: action = "print" if state == "resume" else state self._manager.put(self._createEmptyRequest(url), json.dumps({"action": action}).encode()) + ## Get the preview image data of a print job. + def getPrintJobPreviewImage(self, print_job_uuid: str, on_finished: Callable) -> None: + url = f"{self.CLUSTER_API_PREFIX}/print_jobs/{print_job_uuid}/preview_image" + reply = self._manager.get(self._createEmptyRequest(url)) + self._addCallback(reply, on_finished) + ## We override _createEmptyRequest in order to add the user credentials. # \param url: The URL to request # \param content_type: The type of the body contents. @@ -124,17 +130,23 @@ class ClusterApiClient: reply: QNetworkReply, on_finished: Union[Callable[[ClusterApiClientModel], Any], Callable[[List[ClusterApiClientModel]], Any]], - model: Type[ClusterApiClientModel], + model: Optional[Type[ClusterApiClientModel]] = None, ) -> None: def parse() -> None: # Don't try to parse the reply if we didn't get one if reply.attribute(QNetworkRequest.HttpStatusCodeAttribute) is None: return - status_code, response = self._parseReply(reply) + self._anti_gc_callbacks.remove(parse) - if on_finished: - self._parseModels(response, on_finished, model) - return + + # If no parse model is given, simply return the raw data in the callback. + if not model: + on_finished(reply.readAll()) + return + + # Otherwise parse the result and return the formatted data in the callback. + status_code, response = self._parseReply(reply) + self._parseModels(response, on_finished, model) + self._anti_gc_callbacks.append(parse) - if on_finished: - reply.finished.connect(parse) + reply.finished.connect(parse) diff --git a/plugins/UM3NetworkPrinting/src/Network/NetworkOutputDevice.py b/plugins/UM3NetworkPrinting/src/Network/NetworkOutputDevice.py index e4e9a02062..74f68c0a5e 100644 --- a/plugins/UM3NetworkPrinting/src/Network/NetworkOutputDevice.py +++ b/plugins/UM3NetworkPrinting/src/Network/NetworkOutputDevice.py @@ -2,7 +2,7 @@ # Cura is released under the terms of the LGPLv3 or higher. from typing import Optional, Dict, List, Any -from PyQt5.QtGui import QDesktopServices +from PyQt5.QtGui import QDesktopServices, QImage from PyQt5.QtCore import pyqtSlot, QUrl, pyqtSignal, pyqtProperty from PyQt5.QtNetwork import QNetworkReply @@ -14,6 +14,7 @@ from UM.i18n import i18nCatalog from UM.Scene.SceneNode import SceneNode from cura.PrinterOutput.NetworkedPrinterOutputDevice import AuthState from cura.PrinterOutput.PrinterOutputDevice import ConnectionType +from plugins.UM3NetworkPrinting.src.Models.UM3PrintJobOutputModel import UM3PrintJobOutputModel from .ClusterApiClient import ClusterApiClient from ..ExportFileJob import ExportFileJob @@ -104,9 +105,7 @@ class NetworkOutputDevice(UltimakerNetworkedPrinterOutputDevice): super()._update() self._cluster_api.getPrinters(self._updatePrinters) self._cluster_api.getPrintJobs(self._updatePrintJobs) - # for print_job in self._print_jobs: - # if print_job.getPreviewImage() is None: - # self.get("print_jobs/{uuid}/preview_image".format(uuid=print_job.key), on_finished=self._onGetPreviewImageFinished) + self._updatePrintJobPreviewImages() ## Sync the material profiles in Cura with the printer. # This gets called when connecting to a printer as well as when sending a print. @@ -114,18 +113,6 @@ class NetworkOutputDevice(UltimakerNetworkedPrinterOutputDevice): job = SendMaterialJob(device=self) job.run() - # ## Callback for when preview image was downloaded from cluster. - # def _onGetPreviewImageFinished(self, reply: QNetworkReply) -> None: - # reply_url = reply.url().toString() - # - # uuid = reply_url[reply_url.find("print_jobs/")+len("print_jobs/"):reply_url.rfind("/preview_image")] - # - # print_job = findByKey(self._print_jobs, uuid) - # if print_job: - # image = QImage() - # image.loadFromData(reply.readAll()) - # print_job.updatePreviewImage(image) - ## Send a print job to the cluster. 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: @@ -187,3 +174,9 @@ class NetworkOutputDevice(UltimakerNetworkedPrinterOutputDevice): lifetime=10 ).show() self.writeError.emit() + + ## Download all the images from the cluster and load their data in the print job models. + def _updatePrintJobPreviewImages(self): + for print_job in self._print_jobs: + if print_job.getPreviewImage() is None: + self._cluster_api.getPrintJobPreviewImage(print_job.key, print_job.updatePreviewImageData) diff --git a/plugins/UM3NetworkPrinting/src/UltimakerNetworkedPrinterOutputDevice.py b/plugins/UM3NetworkPrinting/src/UltimakerNetworkedPrinterOutputDevice.py index fedead7bce..2bfacdbb25 100644 --- a/plugins/UM3NetworkPrinting/src/UltimakerNetworkedPrinterOutputDevice.py +++ b/plugins/UM3NetworkPrinting/src/UltimakerNetworkedPrinterOutputDevice.py @@ -4,6 +4,7 @@ import os from typing import List, Optional, Dict from PyQt5.QtCore import pyqtProperty, pyqtSignal, QObject, pyqtSlot, QUrl +from PyQt5.QtGui import QImage from UM.Logger import Logger from UM.Qt.Duration import Duration, DurationFormat