From eb8d353e115eeaaea35c03193b022bd2640e3407 Mon Sep 17 00:00:00 2001 From: ChrisTerBeke Date: Wed, 19 Jun 2019 13:58:11 +0200 Subject: [PATCH] Add basic support for print job actions via Cloud output device --- .../resources/qml/MonitorPrintJobCard.qml | 5 -- .../resources/qml/MonitorPrinterCard.qml | 1 - .../resources/qml/MonitorQueue.qml | 2 - .../src/Cloud/CloudApiClient.py | 15 +++++ .../src/Cloud/CloudOutputController.py | 8 ++- .../src/Cloud/CloudOutputDevice.py | 53 ++++++++++-------- resources/qml/BorderGroup.qmlc.pqgKbT | Bin 0 -> 736 bytes 7 files changed, 50 insertions(+), 34 deletions(-) create mode 100644 resources/qml/BorderGroup.qmlc.pqgKbT diff --git a/plugins/UM3NetworkPrinting/resources/qml/MonitorPrintJobCard.qml b/plugins/UM3NetworkPrinting/resources/qml/MonitorPrintJobCard.qml index 470eb84ac3..fd0870d351 100644 --- a/plugins/UM3NetworkPrinting/resources/qml/MonitorPrintJobCard.qml +++ b/plugins/UM3NetworkPrinting/resources/qml/MonitorPrintJobCard.qml @@ -22,10 +22,6 @@ Item // The print job which all other data is derived from property var printJob: null - // If the printer is a cloud printer or not. Other items base their enabled state off of this boolean. In the future - // they might not need to though. - property bool cloudConnection: Cura.MachineManager.activeMachineIsUsingCloudConnection - width: parent.width height: childrenRect.height @@ -217,7 +213,6 @@ Item } width: 32 * screenScaleFactor // TODO: Theme! height: 32 * screenScaleFactor // TODO: Theme! - enabled: !cloudConnection onClicked: enabled ? contextMenu.switchPopupState() : {} visible: { diff --git a/plugins/UM3NetworkPrinting/resources/qml/MonitorPrinterCard.qml b/plugins/UM3NetworkPrinting/resources/qml/MonitorPrinterCard.qml index f4295ee18d..89687ceeb8 100644 --- a/plugins/UM3NetworkPrinting/resources/qml/MonitorPrinterCard.qml +++ b/plugins/UM3NetworkPrinting/resources/qml/MonitorPrinterCard.qml @@ -172,7 +172,6 @@ Item } width: 36 * screenScaleFactor // TODO: Theme! height: 36 * screenScaleFactor // TODO: Theme! - enabled: !cloudConnection onClicked: enabled ? contextMenu.switchPopupState() : {} visible: diff --git a/plugins/UM3NetworkPrinting/resources/qml/MonitorQueue.qml b/plugins/UM3NetworkPrinting/resources/qml/MonitorQueue.qml index 8460425190..cd5a5d1a37 100644 --- a/plugins/UM3NetworkPrinting/resources/qml/MonitorQueue.qml +++ b/plugins/UM3NetworkPrinting/resources/qml/MonitorQueue.qml @@ -73,8 +73,6 @@ Item MouseArea { anchors.fill: manageQueueLabel - enabled: !cloudConnection - hoverEnabled: !cloudConnection onClicked: Cura.MachineManager.printerOutputDevices[0].openPrintJobControlPanel() onEntered: { diff --git a/plugins/UM3NetworkPrinting/src/Cloud/CloudApiClient.py b/plugins/UM3NetworkPrinting/src/Cloud/CloudApiClient.py index adff94bbbc..4edb30db23 100644 --- a/plugins/UM3NetworkPrinting/src/Cloud/CloudApiClient.py +++ b/plugins/UM3NetworkPrinting/src/Cloud/CloudApiClient.py @@ -96,6 +96,21 @@ class CloudApiClient: reply = self._manager.post(self._createEmptyRequest(url), b"") self._addCallback(reply, on_finished, CloudPrintResponse) + ## Send a print job action to the cluster for the given print job. + # \param cluster_id: The ID of the cluster. + # \param cluster_job_id: The ID of the print job within the cluster. + # \param action: The name of the action to execute. + def doPrintJobAction(self, cluster_id: str, cluster_job_id: str, action: str, data: Dict[str, any] = None) -> None: + body = b"" + if data: + try: + body = json.dumps({"data": data}).encode() + except JSONDecodeError as err: + Logger.log("w", "Could not encode body: %s", err) + return + url = "{}/clusters/{}/print_jobs/{}/action/{}".format(self.CLUSTER_API_ROOT, cluster_id, cluster_job_id, action) + self._manager.post(self._createEmptyRequest(url), body) + ## 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. diff --git a/plugins/UM3NetworkPrinting/src/Cloud/CloudOutputController.py b/plugins/UM3NetworkPrinting/src/Cloud/CloudOutputController.py index bd56ef3185..8c09483990 100644 --- a/plugins/UM3NetworkPrinting/src/Cloud/CloudOutputController.py +++ b/plugins/UM3NetworkPrinting/src/Cloud/CloudOutputController.py @@ -1,5 +1,6 @@ # Copyright (c) 2018 Ultimaker B.V. # Cura is released under the terms of the LGPLv3 or higher. +from cura.PrinterOutput.Models.PrintJobOutputModel import PrintJobOutputModel from cura.PrinterOutput.PrinterOutputController import PrinterOutputController from typing import TYPE_CHECKING @@ -13,10 +14,13 @@ class CloudOutputController(PrinterOutputController): # The cloud connection only supports fetching the printer and queue status and adding a job to the queue. # To let the UI know this we mark all features below as False. - self.can_pause = False - self.can_abort = False + self.can_pause = True + self.can_abort = True self.can_pre_heat_bed = False self.can_pre_heat_hotends = False self.can_send_raw_gcode = False self.can_control_manually = False self.can_update_firmware = False + + def setJobState(self, job: "PrintJobOutputModel", state: str): + self._output_device.setJobState(job.key, state) diff --git a/plugins/UM3NetworkPrinting/src/Cloud/CloudOutputDevice.py b/plugins/UM3NetworkPrinting/src/Cloud/CloudOutputDevice.py index df513f4174..dcbeeb4626 100644 --- a/plugins/UM3NetworkPrinting/src/Cloud/CloudOutputDevice.py +++ b/plugins/UM3NetworkPrinting/src/Cloud/CloudOutputDevice.py @@ -6,6 +6,7 @@ from time import time from typing import Dict, List, Optional, Set, cast from PyQt5.QtCore import QObject, QUrl, pyqtProperty, pyqtSignal, pyqtSlot +from PyQt5.QtGui import QDesktopServices from UM import i18nCatalog from UM.Backend.Backend import BackendState @@ -399,6 +400,22 @@ class CloudOutputDevice(NetworkedPrinterOutputDevice): return [print_job for print_job in self._print_jobs if print_job.assignedPrinter is not None and print_job.state != "queued"] + def setJobState(self, print_job_uuid: str, state: str) -> None: + self._api.doPrintJobAction(self._cluster.cluster_id, print_job_uuid, state) + + @pyqtSlot(str) + def sendJobToTop(self, print_job_uuid: str) -> None: + self._api.doPrintJobAction(self._cluster.cluster_id, print_job_uuid, "move", + {"list": "queued", "to_position": 0}) + + @pyqtSlot(str) + def deleteJobFromQueue(self, print_job_uuid: str) -> None: + self._api.doPrintJobAction(self._cluster.cluster_id, print_job_uuid, "remove") + + @pyqtSlot(str) + def forceSendJob(self, print_job_uuid: str) -> None: + self._api.doPrintJobAction(self._cluster.cluster_id, print_job_uuid, "force") + @pyqtSlot(int, result = str) def formatDuration(self, seconds: int) -> str: return Duration(seconds).getDisplayString(DurationFormat.Format.Short) @@ -411,6 +428,18 @@ class CloudOutputDevice(NetworkedPrinterOutputDevice): def getDateCompleted(self, time_remaining: int) -> str: return formatDateCompleted(time_remaining) + @pyqtProperty(bool, notify=printJobsChanged) + def receivedPrintJobs(self) -> bool: + return bool(self._print_jobs) + + @pyqtSlot() + def openPrintJobControlPanel(self) -> None: + QDesktopServices.openUrl(QUrl("https://mycloud.ultimaker.com")) + + @pyqtSlot() + def openPrinterControlPanel(self) -> None: + QDesktopServices.openUrl(QUrl("https://mycloud.ultimaker.com")) + ## TODO: The following methods are required by the monitor page QML, but are not actually available using cloud. # TODO: We fake the methods here to not break the monitor page. @@ -422,30 +451,6 @@ class CloudOutputDevice(NetworkedPrinterOutputDevice): def setActiveCameraUrl(self, camera_url: "QUrl") -> None: pass - @pyqtProperty(bool, notify = printJobsChanged) - def receivedPrintJobs(self) -> bool: - return bool(self._print_jobs) - - @pyqtSlot() - def openPrintJobControlPanel(self) -> None: - pass - - @pyqtSlot() - def openPrinterControlPanel(self) -> None: - pass - - @pyqtSlot(str) - def sendJobToTop(self, print_job_uuid: str) -> None: - pass - - @pyqtSlot(str) - def deleteJobFromQueue(self, print_job_uuid: str) -> None: - pass - - @pyqtSlot(str) - def forceSendJob(self, print_job_uuid: str) -> None: - pass - @pyqtProperty("QVariantList", notify = _clusterPrintersChanged) def connectedPrintersTypeCount(self) -> List[Dict[str, str]]: return [] diff --git a/resources/qml/BorderGroup.qmlc.pqgKbT b/resources/qml/BorderGroup.qmlc.pqgKbT new file mode 100644 index 0000000000000000000000000000000000000000..0bb07b4a6761aa19a3bc17211da06fd1dc491556 GIT binary patch literal 736 zcmaJ;t4~647(FN;nA}Vjt4S~*VBcVi;&?wU7d0A9j$kktEN%n?b91v9 zbUunR61DkXT+jF2i;v>Rj^FEihx5bEe!{d2$Cw3UI)wY1r+hU4yiWj^r|wYm< z1tQ9jpAs%xN^NI8B^2T*8nT-v07C4I%yS$U=d+FcoGQ#A^iSQ*4{Orqs7BqsG z!4<1<56HFa$};26B}=ru^e4;Rcs^turk=zk5!6cFmC;(>C=vC0kLArmI$sS$F;t6k z|J#*x5iA8FxX}F({~i<4-4f5li1;MVXzK0fL6Gmw!XbL7z(h^N81j3|d<#WXQR2qY zxp+As(_&v{Exm~r>V)n0MRta-wawWc`E_cnAg-S>xefMlRW0$Z$gZZ7G$D zY*0&fw(@(-2CFpvdX@QI#Sr7hCbvr!*_&F&(V3h)IeS!b94 literal 0 HcmV?d00001