Browse Source

Add basic support for print job actions via Cloud output device

ChrisTerBeke 5 years ago
parent
commit
eb8d353e11

+ 0 - 5
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:
         {

+ 0 - 1
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:

+ 0 - 2
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:
         {

+ 15 - 0
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.

+ 6 - 2
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)

+ 27 - 22
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,39 +428,27 @@ class CloudOutputDevice(NetworkedPrinterOutputDevice):
     def getDateCompleted(self, time_remaining: int) -> str:
         return formatDateCompleted(time_remaining)
 
-    ##  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.
-
-    @pyqtProperty(QUrl, notify = _clusterPrintersChanged)
-    def activeCameraUrl(self) -> "QUrl":
-        return QUrl()
-
-    @pyqtSlot(QUrl)
-    def setActiveCameraUrl(self, camera_url: "QUrl") -> None:
-        pass
-
-    @pyqtProperty(bool, notify = printJobsChanged)
+    @pyqtProperty(bool, notify=printJobsChanged)
     def receivedPrintJobs(self) -> bool:
         return bool(self._print_jobs)
 
     @pyqtSlot()
     def openPrintJobControlPanel(self) -> None:
-        pass
+        QDesktopServices.openUrl(QUrl("https://mycloud.ultimaker.com"))
 
     @pyqtSlot()
     def openPrinterControlPanel(self) -> None:
-        pass
+        QDesktopServices.openUrl(QUrl("https://mycloud.ultimaker.com"))
 
-    @pyqtSlot(str)
-    def sendJobToTop(self, print_job_uuid: str) -> None:
-        pass
+    ##  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.
 
-    @pyqtSlot(str)
-    def deleteJobFromQueue(self, print_job_uuid: str) -> None:
-        pass
+    @pyqtProperty(QUrl, notify = _clusterPrintersChanged)
+    def activeCameraUrl(self) -> "QUrl":
+        return QUrl()
 
-    @pyqtSlot(str)
-    def forceSendJob(self, print_job_uuid: str) -> None:
+    @pyqtSlot(QUrl)
+    def setActiveCameraUrl(self, camera_url: "QUrl") -> None:
         pass
 
     @pyqtProperty("QVariantList", notify = _clusterPrintersChanged)

BIN
resources/qml/BorderGroup.qmlc.pqgKbT