diff --git a/cura/CuraApplication.py b/cura/CuraApplication.py index df25522be3..c29ddf10fd 100755 --- a/cura/CuraApplication.py +++ b/cura/CuraApplication.py @@ -94,6 +94,7 @@ from . import CuraActions from cura.Scene import ZOffsetDecorator from . import CuraSplashScreen from . import CameraImageProvider +from . import PrintJobPreviewImageProvider from . import MachineActionManager from cura.TaskManagement.OnExitCallbackManager import OnExitCallbackManager @@ -523,6 +524,7 @@ class CuraApplication(QtApplication): def _onEngineCreated(self): self._qml_engine.addImageProvider("camera", CameraImageProvider.CameraImageProvider()) + self._qml_engine.addImageProvider("print_job_preview", PrintJobPreviewImageProvider.PrintJobPreviewImageProvider()) @pyqtProperty(bool) def needToShowUserAgreement(self): diff --git a/cura/PrintJobPreviewImageProvider.py b/cura/PrintJobPreviewImageProvider.py new file mode 100644 index 0000000000..d3521bf0af --- /dev/null +++ b/cura/PrintJobPreviewImageProvider.py @@ -0,0 +1,27 @@ +from PyQt5.QtGui import QImage +from PyQt5.QtQuick import QQuickImageProvider +from PyQt5.QtCore import QSize + +from UM.Application import Application + + +class PrintJobPreviewImageProvider(QQuickImageProvider): + def __init__(self): + super().__init__(QQuickImageProvider.Image) + + ## Request a new image. + def requestImage(self, id, size): + # The id will have an uuid and an increment separated by a slash. As we don't care about the value of the + # increment, we need to strip that first. + uuid = id[id.find("/") + 1:] + for output_device in Application.getInstance().getOutputDeviceManager().getOutputDevices(): + if not hasattr(output_device, "printJobs"): + continue + + for print_job in output_device.printJobs: + if print_job.key == uuid: + if print_job.getPreviewImage(): + return print_job.getPreviewImage(), QSize(15, 15) + else: + return QImage(), QSize(15, 15) + return QImage(), QSize(15,15) \ No newline at end of file diff --git a/cura/PrinterOutput/PrintJobOutputModel.py b/cura/PrinterOutput/PrintJobOutputModel.py index 8057965013..373f816373 100644 --- a/cura/PrinterOutput/PrintJobOutputModel.py +++ b/cura/PrinterOutput/PrintJobOutputModel.py @@ -4,6 +4,9 @@ from PyQt5.QtCore import pyqtSignal, pyqtProperty, QObject, pyqtSlot from typing import Optional, TYPE_CHECKING +from PyQt5.QtCore import QUrl +from PyQt5.QtGui import QImage + if TYPE_CHECKING: from cura.PrinterOutput.PrinterOutputController import PrinterOutputController from cura.PrinterOutput.PrinterOutputModel import PrinterOutputModel @@ -18,7 +21,8 @@ class PrintJobOutputModel(QObject): keyChanged = pyqtSignal() assignedPrinterChanged = pyqtSignal() ownerChanged = pyqtSignal() - configurationChanged =pyqtSignal() + configurationChanged = pyqtSignal() + previewImageChanged = pyqtSignal() def __init__(self, output_controller: "PrinterOutputController", key: str = "", name: str = "", parent=None) -> None: super().__init__(parent) @@ -33,6 +37,27 @@ class PrintJobOutputModel(QObject): self._configuration = None # type: Optional[ConfigurationModel] + self._preview_image_id = 0 + + self._preview_image = None + + @pyqtProperty(QUrl, notify=previewImageChanged) + def preview_image_url(self): + self._preview_image_id += 1 + # There is an image provider that is called "camera". In order to ensure that the image qml object, that + # requires a QUrl to function, updates correctly we add an increasing number. This causes to see the QUrl + # as new (instead of relying on cached version and thus forces an update. + temp = "image://print_job_preview/" + str(self._preview_image_id) + "/" + self._key + return QUrl(temp, QUrl.TolerantMode) + + def getPreviewImage(self): + return self._preview_image + + def updatePreviewImage(self, preview_image: Optional[QImage]): + if self._preview_image != preview_image: + self._preview_image = preview_image + self.previewImageChanged.emit() + @pyqtProperty(QObject, notify=configurationChanged) def configuration(self) -> Optional["ConfigurationModel"]: return self._configuration diff --git a/plugins/UM3NetworkPrinting/ClusterMonitorItem.qml b/plugins/UM3NetworkPrinting/ClusterMonitorItem.qml index 51301b7e8d..3bc9fedc9c 100644 --- a/plugins/UM3NetworkPrinting/ClusterMonitorItem.qml +++ b/plugins/UM3NetworkPrinting/ClusterMonitorItem.qml @@ -82,12 +82,13 @@ Component leftMargin: UM.Theme.getSize("default_lining").width // To ensure border can be drawn. rightMargin: UM.Theme.getSize("default_lining").width right: parent.right + bottom: parent.bottom } ListView { anchors.fill: parent - spacing: -UM.Theme.getSize("default_lining").height + spacing: UM.Theme.getSize("default_margin").height model: OutputDevice.queuedPrintJobs diff --git a/plugins/UM3NetworkPrinting/ClusterUM3OutputDevice.py b/plugins/UM3NetworkPrinting/ClusterUM3OutputDevice.py index d91e7e1d93..b79ad6b5ce 100644 --- a/plugins/UM3NetworkPrinting/ClusterUM3OutputDevice.py +++ b/plugins/UM3NetworkPrinting/ClusterUM3OutputDevice.py @@ -29,7 +29,7 @@ from .ClusterUM3PrinterOutputController import ClusterUM3PrinterOutputController from .SendMaterialJob import SendMaterialJob from PyQt5.QtNetwork import QNetworkRequest, QNetworkReply -from PyQt5.QtGui import QDesktopServices +from PyQt5.QtGui import QDesktopServices, QImage from PyQt5.QtCore import pyqtSlot, QUrl, pyqtSignal, pyqtProperty, QObject from time import time @@ -394,11 +394,28 @@ class ClusterUM3OutputDevice(NetworkedPrinterOutputDevice): super().connect() self.sendMaterialProfiles() + def _onGetPreviewImageFinished(self, reply: QNetworkReply) -> None: + reply_url = reply.url().toString() + print(reply_url) + + 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) + + def _update(self) -> None: super()._update() self.get("printers/", on_finished = self._onGetPrintersDataFinished) self.get("print_jobs/", on_finished = self._onGetPrintJobsFinished) + 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) + def _onGetPrintJobsFinished(self, reply: QNetworkReply) -> None: if not checkValidGetReply(reply): return diff --git a/plugins/UM3NetworkPrinting/PrintJobInfoBlock.qml b/plugins/UM3NetworkPrinting/PrintJobInfoBlock.qml index f88b917954..7ae65dfb9b 100644 --- a/plugins/UM3NetworkPrinting/PrintJobInfoBlock.qml +++ b/plugins/UM3NetworkPrinting/PrintJobInfoBlock.qml @@ -44,6 +44,15 @@ Item text: "OwnerName" } + Image + { + source: printJob.preview_image_url + anchors.top: ownerName.bottom + anchors.horizontalCenter: parent.horizontalCenter + anchors.bottom: totalTimeLabel.top + width: height + } + Label { id: totalTimeLabel