diff --git a/plugins/UM3NetworkPrinting/resources/png/Ultimaker 3 Extended.png b/plugins/UM3NetworkPrinting/resources/png/Ultimaker 3 Extended.png new file mode 100644 index 0000000000..1ce19c2933 Binary files /dev/null and b/plugins/UM3NetworkPrinting/resources/png/Ultimaker 3 Extended.png differ diff --git a/plugins/UM3NetworkPrinting/resources/png/Ultimaker 3.png b/plugins/UM3NetworkPrinting/resources/png/Ultimaker 3.png new file mode 100644 index 0000000000..4639cb3fde Binary files /dev/null and b/plugins/UM3NetworkPrinting/resources/png/Ultimaker 3.png differ diff --git a/plugins/UM3NetworkPrinting/resources/png/Ultimaker S5.png b/plugins/UM3NetworkPrinting/resources/png/Ultimaker S5.png new file mode 100644 index 0000000000..29ba428e38 Binary files /dev/null and b/plugins/UM3NetworkPrinting/resources/png/Ultimaker S5.png differ diff --git a/plugins/UM3NetworkPrinting/resources/qml/CameraButton.qml b/plugins/UM3NetworkPrinting/resources/qml/CameraButton.qml index 7e5c254e5c..618dbed81c 100644 --- a/plugins/UM3NetworkPrinting/resources/qml/CameraButton.qml +++ b/plugins/UM3NetworkPrinting/resources/qml/CameraButton.qml @@ -9,10 +9,10 @@ import Cura 1.0 as Cura Rectangle { property var iconSource: null; - color: clickArea.containsMouse ? UM.Theme.getColor("primary_hover") : UM.Theme.getColor("primary"); // "Cura Blue" + color: "#0a0850" // TODO: Theme! height: width; radius: Math.round(0.5 * width); - width: 36 * screenScaleFactor; + width: 24 * screenScaleFactor; UM.RecolorImage { id: icon; diff --git a/plugins/UM3NetworkPrinting/resources/qml/ClusterMonitorItem.qml b/plugins/UM3NetworkPrinting/resources/qml/ClusterMonitorItem.qml index 19a152e6eb..6bbc338c17 100644 --- a/plugins/UM3NetworkPrinting/resources/qml/ClusterMonitorItem.qml +++ b/plugins/UM3NetworkPrinting/resources/qml/ClusterMonitorItem.qml @@ -10,14 +10,13 @@ import QtGraphicalEffects 1.0 Component { - Rectangle + Item { id: monitorFrame property var emphasisColor: UM.Theme.getColor("setting_control_border_highlight") property var cornerRadius: UM.Theme.getSize("monitor_corner_radius").width - color: "transparent" height: maximumHeight onVisibleChanged: { @@ -48,13 +47,44 @@ Component } } + ScrollView + { + id: printers + anchors + { + left: parent.left + right: parent.right + top: parent.top + topMargin: 48 * screenScaleFactor // TODO: Theme! + } + height: 264 * screenScaleFactor // TODO: Theme! + Row + { + spacing: 60 * screenScaleFactor // TODO: Theme! + + Repeater + { + model: OutputDevice.printers + + MonitorPrinterCard + { + printer: modelData + } + } + } + } + Item { id: queue - anchors.fill: parent - anchors.top: parent.top - anchors.topMargin: 400 * screenScaleFactor // TODO: Insert carousel here + anchors { + bottom: parent.bottom + left: parent.left + right: parent.right + top: printers.bottom + topMargin: 48 + } Label { diff --git a/plugins/UM3NetworkPrinting/resources/qml/MonitorPrintJobProgressBar.qml b/plugins/UM3NetworkPrinting/resources/qml/MonitorPrintJobProgressBar.qml new file mode 100644 index 0000000000..f70e1175a1 --- /dev/null +++ b/plugins/UM3NetworkPrinting/resources/qml/MonitorPrintJobProgressBar.qml @@ -0,0 +1,137 @@ +// Copyright (c) 2018 Ultimaker B.V. +// Cura is released under the terms of the LGPLv3 or higher. + +import QtQuick 2.3 +import QtQuick.Controls.Styles 1.3 +import QtQuick.Controls 1.4 +import UM 1.3 as UM + +/** + * NOTE: For most labels, a fixed height with vertical alignment is used to make + * layouts more deterministic (like the fixed-size textboxes used in original + * mock-ups). This is also a stand-in for CSS's 'line-height' property. Denoted + * with '// FIXED-LINE-HEIGHT:'. + */ +Item +{ + id: base + property var printJob: null + property var progress: + { + if (!printJob) + { + return 0 + } + var result = printJob.timeElapsed / printJob.timeTotal + if (result > 1.0) + { + result = 1.0 + } + return result + } + property var remainingTime: + { + if (!printJob) { + return 0 + } + /* Sometimes total minus elapsed is less than 0. Use Math.max() to prevent remaining + time from ever being less than 0. Negative durations cause strange behavior such + as displaying "-1h -1m". */ + return Math.max(printer.activePrintJob.timeTotal - printer.activePrintJob.timeElapsed, 0) + } + property var progressText: + { + if (!printJob) + { + return ""; + } + switch (printJob.state) + { + case "wait_cleanup": + if (printJob.timeTotal > printJob.timeElapsed) + { + return catalog.i18nc("@label:status", "Aborted") + } + return catalog.i18nc("@label:status", "Finished") + case "pre_print": + case "sent_to_printer": + return catalog.i18nc("@label:status", "Preparing") + case "aborted": + return catalog.i18nc("@label:status", "Aborted") + case "wait_user_action": + return catalog.i18nc("@label:status", "Aborted") + case "pausing": + return catalog.i18nc("@label:status", "Pausing") + case "paused": + return OutputDevice.formatDuration( remainingTime ) + case "resuming": + return catalog.i18nc("@label:status", "Resuming") + case "queued": + return catalog.i18nc("@label:status", "Action required") + default: + return OutputDevice.formatDuration( remainingTime ) + } + } + width: childrenRect.width + height: 18 * screenScaleFactor // TODO: Theme! + + ProgressBar + { + id: progressBar + anchors + { + verticalCenter: parent.verticalCenter + } + value: progress; + style: ProgressBarStyle + { + background: Rectangle + { + color: "#e4e4f2" // TODO: Theme! + implicitHeight: visible ? 8 * screenScaleFactor : 0 // TODO: Theme! + implicitWidth: 180 * screenScaleFactor // TODO: Theme! + radius: 4 * screenScaleFactor // TODO: Theme! + } + progress: Rectangle + { + id: progressItem; + color: + { + if (printJob) + { + var state = printJob.state + var inactiveStates = [ + "pausing", + "paused", + "resuming", + "wait_cleanup" + ] + if (inactiveStates.indexOf(state) > -1 && remainingTime > 0) + { + return UM.Theme.getColor("monitor_progress_fill_inactive") + } + } + return "#0a0850" // TODO: Theme! + } + radius: 4 * screenScaleFactor // TODO: Theme! + } + } + } + Label + { + id: progressLabel + anchors + { + left: progressBar.right + leftMargin: 18 * screenScaleFactor // TODO: Theme! + } + text: progressText + color: "#374355" // TODO: Theme! + width: contentWidth + font: UM.Theme.getFont("medium") // 14pt, regular + + // FIXED-LINE-HEIGHT: + height: 18 * screenScaleFactor // TODO: Theme! + verticalAlignment: Text.AlignVCenter + } +} \ No newline at end of file diff --git a/plugins/UM3NetworkPrinting/resources/qml/MonitorPrinterCard.qml b/plugins/UM3NetworkPrinting/resources/qml/MonitorPrinterCard.qml new file mode 100644 index 0000000000..975fe12244 --- /dev/null +++ b/plugins/UM3NetworkPrinting/resources/qml/MonitorPrinterCard.qml @@ -0,0 +1,242 @@ +// Copyright (c) 2018 Ultimaker B.V. +// Cura is released under the terms of the LGPLv3 or higher. + +import QtQuick 2.3 +import QtQuick.Controls 2.0 +import UM 1.3 as UM + +/** + * A Printer Card is has two main components: the printer portion and the print + * job portion, the latter being paired in the UI when a print job is paired + * a printer in-cluster. + * + * NOTE: For most labels, a fixed height with vertical alignment is used to make + * layouts more deterministic (like the fixed-size textboxes used in original + * mock-ups). This is also a stand-in for CSS's 'line-height' property. Denoted + * with '// FIXED-LINE-HEIGHT:'. + */ +Item +{ + id: base + + // The printer which all printer data is derived from + property var printer: null + + property var borderSize: 1 * screenScaleFactor // TODO: Theme, and remove from here + + width: 834 * screenScaleFactor // TODO: Theme! + height: 216 * screenScaleFactor // TODO: Theme! + + // Printer portion + Rectangle + { + id: printerInfo + border + { + color: "#EAEAEC" // TODO: Theme! + width: borderSize // TODO: Remove once themed + } + color: "white" // TODO: Theme! + width: parent.width + height: 144 * screenScaleFactor // TODO: Theme! + + Row + { + anchors + { + left: parent.left + leftMargin: 36 * screenScaleFactor // TODO: Theme! + verticalCenter: parent.verticalCenter + } + spacing: 18 * screenScaleFactor // TODO: Theme! + + Image + { + id: printerImage + width: 108 * screenScaleFactor // TODO: Theme! + height: 108 * screenScaleFactor // TODO: Theme! + fillMode: Image.PreserveAspectFit + source: "../png/" + printer.type + ".png" + mipmap: true + } + + Item + { + anchors + { + verticalCenter: parent.verticalCenter + } + width: 216 * screenScaleFactor // TODO: Theme! + height: printerNameLabel.height + printerFamilyPill.height + 6 * screenScaleFactor // TODO: Theme! + + Label + { + id: printerNameLabel + text: printer && printer.name ? printer.name : "" + color: "#414054" // TODO: Theme! + elide: Text.ElideRight + font: UM.Theme.getFont("large") // 16pt, bold + width: parent.width + + // FIXED-LINE-HEIGHT: + height: 18 * screenScaleFactor // TODO: Theme! + verticalAlignment: Text.AlignVCenter + } + + MonitorPrinterPill + { + id: printerFamilyPill + anchors + { + top: printerNameLabel.bottom + topMargin: 6 * screenScaleFactor // TODO: Theme! + left: printerNameLabel.left + } + text: printer.type + } + } + + MonitorPrinterConfiguration + { + id: printerConfiguration + anchors.verticalCenter: parent.verticalCenter + buildplate: "Glass" + configurations: + [ + base.printer.printerConfiguration.extruderConfigurations[0], + base.printer.printerConfiguration.extruderConfigurations[1] + ] + height: 72 * screenScaleFactor // TODO: Theme! + } + } + + PrintJobContextMenu + { + id: contextButton + anchors + { + right: parent.right + rightMargin: 12 * screenScaleFactor // TODO: Theme! + top: parent.top + topMargin: 12 * screenScaleFactor // TODO: Theme! + } + printJob: printer.activePrintJob + width: 36 * screenScaleFactor // TODO: Theme! + height: 36 * screenScaleFactor // TODO: Theme! + } + CameraButton + { + id: cameraButton; + anchors + { + right: parent.right + rightMargin: 20 * screenScaleFactor // TODO: Theme! + bottom: parent.bottom + bottomMargin: 20 * screenScaleFactor // TODO: Theme! + } + iconSource: "../svg/icons/camera.svg" + } + } + + + // Print job portion + Rectangle + { + id: printJobInfo + anchors + { + top: printerInfo.bottom + topMargin: -borderSize * screenScaleFactor // TODO: Theme! + } + border + { + color: "#EAEAEC" // TODO: Theme! + width: borderSize // TODO: Remove once themed + } + color: "white" // TODO: Theme! + height: 84 * screenScaleFactor + borderSize // TODO: Remove once themed + width: parent.width + + Row + { + anchors + { + fill: parent + topMargin: 12 * screenScaleFactor + borderSize // TODO: Theme! + bottomMargin: 12 * screenScaleFactor // TODO: Theme! + leftMargin: 36 * screenScaleFactor // TODO: Theme! + } + height: childrenRect.height + spacing: 18 * screenScaleFactor // TODO: Theme! + + Item + { + anchors + { + verticalCenter: parent.verticalCenter + } + width: printerImage.width + height: 60 * screenScaleFactor // TODO: Theme! + MonitorPrintJobPreview + { + anchors.centerIn: parent + printJob: base.printer.activePrintJob + size: parent.height + } + } + + Item + { + anchors + { + verticalCenter: parent.verticalCenter + } + width: 216 * screenScaleFactor // TODO: Theme! + height: printerNameLabel.height + printerFamilyPill.height + 6 * screenScaleFactor // TODO: Theme! + + Label + { + id: printerJobNameLabel + text: base.printer.activePrintJob ? base.printer.activePrintJob.name : "Untitled" // TODO: I18N + color: "#414054" // TODO: Theme! + elide: Text.ElideRight + font: UM.Theme.getFont("large") // 16pt, bold + width: parent.width + + // FIXED-LINE-HEIGHT: + height: 18 * screenScaleFactor // TODO: Theme! + verticalAlignment: Text.AlignVCenter + } + + Label + { + id: printerJobOwnerLabel + anchors + { + top: printerJobNameLabel.bottom + topMargin: 6 * screenScaleFactor // TODO: Theme! + left: printerJobNameLabel.left + } + text: printer.activePrintJob ? printer.activePrintJob.owner : "Anonymous" // TODO: I18N + color: "#53657d" // TODO: Theme! + elide: Text.ElideRight + font: UM.Theme.getFont("very_small") // 12pt, regular + width: parent.width + + // FIXED-LINE-HEIGHT: + height: 18 * screenScaleFactor // TODO: Theme! + verticalAlignment: Text.AlignVCenter + } + } + + MonitorPrintJobProgressBar + { + anchors + { + verticalCenter: parent.verticalCenter + } + printJob: printer.activePrintJob + } + } + } +} \ No newline at end of file diff --git a/plugins/UM3NetworkPrinting/resources/qml/PrintJobContextMenu.qml b/plugins/UM3NetworkPrinting/resources/qml/PrintJobContextMenu.qml index 11bc913d06..02a8e7ae69 100644 --- a/plugins/UM3NetworkPrinting/resources/qml/PrintJobContextMenu.qml +++ b/plugins/UM3NetworkPrinting/resources/qml/PrintJobContextMenu.qml @@ -25,7 +25,7 @@ Item { } contentItem: Label { color: UM.Theme.getColor("monitor_context_menu_dots"); - font.pixelSize: 25 * screenScaleFactor; + font.pixelSize: 32 * screenScaleFactor; horizontalAlignment: Text.AlignHCenter; text: button.text; verticalAlignment: Text.AlignVCenter; @@ -41,7 +41,7 @@ Item { var states = ["queued", "sent_to_printer", "pre_print", "printing", "pausing", "paused", "resuming"]; return states.indexOf(printJob.state) !== -1; } - width: 35 * screenScaleFactor; // TODO: Theme! + width: 36 * screenScaleFactor; // TODO: Theme! } Popup { diff --git a/plugins/UM3NetworkPrinting/resources/svg/icons/camera.svg b/plugins/UM3NetworkPrinting/resources/svg/icons/camera.svg new file mode 100644 index 0000000000..2eaebb812d --- /dev/null +++ b/plugins/UM3NetworkPrinting/resources/svg/icons/camera.svg @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/plugins/UM3NetworkPrinting/src/ClusterUM3OutputDevice.py b/plugins/UM3NetworkPrinting/src/ClusterUM3OutputDevice.py index 8314b0f089..3b124faf66 100644 --- a/plugins/UM3NetworkPrinting/src/ClusterUM3OutputDevice.py +++ b/plugins/UM3NetworkPrinting/src/ClusterUM3OutputDevice.py @@ -65,7 +65,6 @@ class ClusterUM3OutputDevice(NetworkedPrinterOutputDevice): self._received_print_jobs = False # type: bool self._monitor_view_qml_path = os.path.join(os.path.dirname(os.path.abspath(__file__)), "../resources/qml/ClusterMonitorItem.qml") - self._control_view_qml_path = os.path.join(os.path.dirname(os.path.abspath(__file__)), "../resources/qml/ClusterControlItem.qml") # See comments about this hack with the clusterPrintersChanged signal self.printersChanged.connect(self.clusterPrintersChanged)