Browse Source

Merge pull request #4841 from Ultimaker/CL-1148_restyling_monitor_queue_tiles

CL-1148 Re-styling monitor queue tiles
Simon Edwards 6 years ago
parent
commit
ee7355c2bb

+ 181 - 95
plugins/UM3NetworkPrinting/resources/qml/ClusterMonitorItem.qml

@@ -6,127 +6,213 @@ import QtQuick.Controls 1.4
 import QtQuick.Controls.Styles 1.4
 import UM 1.3 as UM
 import Cura 1.0 as Cura
+import QtGraphicalEffects 1.0
 
-Component {
-    Rectangle {
-        id: monitorFrame;
-        property var emphasisColor: UM.Theme.getColor("setting_control_border_highlight");
-        property var cornerRadius: UM.Theme.getSize("monitor_corner_radius").width;
-        color: UM.Theme.getColor("viewport_background");
-        height: maximumHeight;
-        onVisibleChanged: {
-            if (monitorFrame != null && !monitorFrame.visible) {
-                OutputDevice.setActiveCameraUrl("");
-            }
-        }
-        width: maximumWidth;
+Component
+{
+    Rectangle
+    {
+        id: monitorFrame
 
-        UM.I18nCatalog {
-            id: catalog;
-            name: "cura";
-        }
+        property var emphasisColor: UM.Theme.getColor("setting_control_border_highlight")
+        property var cornerRadius: UM.Theme.getSize("monitor_corner_radius").width
 
-        Label {
-            id: manageQueueLabel;
-            anchors {
-                bottom: queuedLabel.bottom;
-                right: queuedPrintJobs.right;
-                rightMargin: 3 * UM.Theme.getSize("default_margin").width;
+        color: "transparent"
+        height: maximumHeight
+        onVisibleChanged:
+        {
+            if (monitorFrame != null && !monitorFrame.visible)
+            {
+                OutputDevice.setActiveCameraUrl("")
             }
-            color: UM.Theme.getColor("primary");
-            font: UM.Theme.getFont("default");
-            linkColor: UM.Theme.getColor("primary");
-            text: catalog.i18nc("@label link to connect manager", "Manage queue");
         }
+        width: maximumWidth
 
-        MouseArea {
-            anchors.fill: manageQueueLabel;
-            hoverEnabled: true;
-            onClicked: Cura.MachineManager.printerOutputDevices[0].openPrintJobControlPanel();
-            onEntered: manageQueueLabel.font.underline = true;
-            onExited: manageQueueLabel.font.underline = false;
+        UM.I18nCatalog
+        {
+            id: catalog
+            name: "cura"
         }
 
-        Label {
-            id: queuedLabel;
-            anchors {
-                left: queuedPrintJobs.left;
-                leftMargin: 3 * UM.Theme.getSize("default_margin").width + 5 * screenScaleFactor;
-                top: parent.top;
-                topMargin: 2 * UM.Theme.getSize("default_margin").height;
+        LinearGradient {
+            anchors.fill: parent
+            gradient: Gradient {
+                GradientStop {
+                    position: 0.0
+                    color: "#f6f6f6"
+                }
+                GradientStop {
+                    position: 1.0
+                    color: "#ffffff"
+                }
             }
-            color: UM.Theme.getColor("text");
-            font: UM.Theme.getFont("large");
-            text: catalog.i18nc("@label", "Queued");
         }
 
-        Column {
-            id: skeletonLoader;
-            anchors {
-                bottom: parent.bottom;
-                bottomMargin: UM.Theme.getSize("default_margin").height;
-                horizontalCenter: parent.horizontalCenter;
-                top: queuedLabel.bottom;
-                topMargin: UM.Theme.getSize("default_margin").height;
+        Item
+        {
+            id: queue
+
+            anchors.fill: parent
+            anchors.top: parent.top
+            anchors.topMargin: 400 * screenScaleFactor // TODO: Insert carousel here
+
+            Label
+            {
+                id: queuedLabel
+                anchors
+                {
+                    left: queuedPrintJobs.left
+                    top: parent.top
+                }
+                color: UM.Theme.getColor("text")
+                font: UM.Theme.getFont("large_nonbold")
+                text: catalog.i18nc("@label", "Queued")
             }
-            visible: !queuedPrintJobs.visible;
-            width: Math.min(800 * screenScaleFactor, maximumWidth);
 
-            PrintJobInfoBlock {
-                anchors {
-                    left: parent.left;
-                    leftMargin: UM.Theme.getSize("default_margin").width;
-                    right: parent.right;
-                    rightMargin: UM.Theme.getSize("default_margin").width;
+            Item
+            {
+                id: manageQueueLabel
+                anchors
+                {
+                    right: queuedPrintJobs.right
+                    verticalCenter: queuedLabel.verticalCenter
+                }
+                height: 18 * screenScaleFactor // TODO: Theme!
+                width: childrenRect.width
+
+                UM.RecolorImage
+                {
+                    id: externalLinkIcon
+                    anchors.verticalCenter: manageQueueLabel.verticalCenter
+                    color: UM.Theme.getColor("primary")
+                    source: "../svg/icons/external_link.svg"
+                    width: 16 * screenScaleFactor // TODO: Theme! (Y U NO USE 18 LIKE ALL OTHER ICONS?!)
+                    height: 16 * screenScaleFactor // TODO: Theme! (Y U NO USE 18 LIKE ALL OTHER ICONS?!)
+                }
+                Label
+                {
+                    id: manageQueueText
+                    anchors
+                    {
+                        left: externalLinkIcon.right
+                        leftMargin: 6 * screenScaleFactor // TODO: Theme!
+                        verticalCenter: externalLinkIcon.verticalCenter
+                    }
+                    color: UM.Theme.getColor("primary")
+                    font: UM.Theme.getFont("default")
+                    linkColor: UM.Theme.getColor("primary")
+                    text: catalog.i18nc("@label link to connect manager", "Manage queue in Cura Connect")
                 }
-                printJob: null; // Use as skeleton
             }
+            
 
-            PrintJobInfoBlock {
-                anchors {
-                    left: parent.left;
-                    leftMargin: UM.Theme.getSize("default_margin").width;
-                    right: parent.right;
-                    rightMargin: UM.Theme.getSize("default_margin").width;
+            MouseArea
+            {
+                anchors.fill: manageQueueLabel
+                hoverEnabled: true
+                onClicked: Cura.MachineManager.printerOutputDevices[0].openPrintJobControlPanel()
+                onEntered:
+                {
+                    manageQueueText.font.underline = true
+                }
+                onExited:
+                {
+                    manageQueueText.font.underline = false
                 }
-                printJob: null; // Use as skeleton
             }
-        }
 
-        ScrollView {
-            id: queuedPrintJobs;
-            anchors {
-                top: queuedLabel.bottom;
-                topMargin: UM.Theme.getSize("default_margin").height;
-                horizontalCenter: parent.horizontalCenter;
-                bottomMargin: UM.Theme.getSize("default_margin").height;
-                bottom: parent.bottom;
+            Row
+            {
+                id: printJobQueueHeadings
+                anchors
+                {
+                    left: queuedPrintJobs.left
+                    leftMargin: 6 * screenScaleFactor // TODO: Theme!
+                    top: queuedLabel.bottom
+                    topMargin: 24 * screenScaleFactor // TODO: Theme!
+                }
+                spacing: 18 * screenScaleFactor // TODO: Theme!
+
+                Label
+                {
+                    text: catalog.i18nc("@label", "Print jobs")
+                    color: "#666666"
+                    elide: Text.ElideRight
+                    font: UM.Theme.getFont("medium") // 14pt, regular
+                    anchors.verticalCenter: parent.verticalCenter
+                    width: 284 * screenScaleFactor // TODO: Theme! (Should match column size)
+
+                    // FIXED-LINE-HEIGHT:
+                    height: 18 * screenScaleFactor // TODO: Theme!
+                    verticalAlignment: Text.AlignVCenter
+                }
+
+                Label
+                {
+                    text: catalog.i18nc("@label", "Total print time")
+                    color: "#666666"
+                    elide: Text.ElideRight
+                    font: UM.Theme.getFont("medium") // 14pt, regular
+                    anchors.verticalCenter: parent.verticalCenter
+                    width: 216 * screenScaleFactor // TODO: Theme! (Should match column size)
+
+                    // FIXED-LINE-HEIGHT:
+                    height: 18 * screenScaleFactor // TODO: Theme!
+                    verticalAlignment: Text.AlignVCenter
+                }
+
+                Label
+                {
+                    text: catalog.i18nc("@label", "Waiting for")
+                    color: "#666666"
+                    elide: Text.ElideRight
+                    font: UM.Theme.getFont("medium") // 14pt, regular
+                    anchors.verticalCenter: parent.verticalCenter
+                    width: 216 * screenScaleFactor // TODO: Theme! (Should match column size)
+
+                    // FIXED-LINE-HEIGHT:
+                    height: 18 * screenScaleFactor // TODO: Theme!
+                    verticalAlignment: Text.AlignVCenter
+                }
             }
-            style: UM.Theme.styles.scrollview;
-            visible: OutputDevice.receivedPrintJobs;
-            width: Math.min(800 * screenScaleFactor, maximumWidth);
-
-            ListView {
-                id: printJobList;
-                anchors.fill: parent;
-                delegate: PrintJobInfoBlock {
-                    anchors {
-                        left: parent.left;
-                        leftMargin: UM.Theme.getSize("default_margin").width;
-                        right: parent.right;
-                        rightMargin: UM.Theme.getSize("default_margin").width;
+
+            ScrollView
+            {
+                id: queuedPrintJobs
+                anchors {
+                    bottom: parent.bottom
+                    horizontalCenter: parent.horizontalCenter
+                    top: printJobQueueHeadings.bottom
+                    topMargin: 12 * screenScaleFactor // TODO: Theme!
+                }
+                style: UM.Theme.styles.scrollview
+                visible: OutputDevice.receivedPrintJobs
+                width: Math.min(834 * screenScaleFactor, maximumWidth)
+
+                ListView
+                {
+                    id: printJobList
+                    anchors.fill: parent
+                    delegate: MonitorPrintJobCard
+                    {
+                        anchors
+                        {
+                            left: parent.left
+                            right: parent.right
+                        }
+                        printJob: modelData
                     }
-                    printJob: modelData;
+                    model: OutputDevice.queuedPrintJobs
+                    spacing: 6
                 }
-                model: OutputDevice.queuedPrintJobs;
-                spacing: UM.Theme.getSize("default_margin").height - 2 * UM.Theme.getSize("monitor_shadow_radius").width;
             }
         }
 
         PrinterVideoStream {
-            anchors.fill: parent;
-            cameraUrl: OutputDevice.activeCameraUrl;
-            visible: OutputDevice.activeCameraUrl != "";
+            anchors.fill: parent
+            cameraUrl: OutputDevice.activeCameraUrl
+            visible: OutputDevice.activeCameraUrl != ""
         }
     }
+    
 }

+ 82 - 0
plugins/UM3NetworkPrinting/resources/qml/ExpandableCard.qml

@@ -0,0 +1,82 @@
+// Copyright (c) 2018 Ultimaker B.V.
+// Cura is released under the terms of the LGPLv3 or higher.
+
+import QtQuick 2.2
+import QtQuick.Controls 2.0
+import UM 1.3 as UM
+import Cura 1.0 as Cura
+
+// TODO: Theme & documentation!
+// The expandable component has 3 major sub components:
+//      * The headerItem Always visible and should hold some info about what happens if the component is expanded
+//      * The popupItem The content that needs to be shown if the component is expanded.
+Item
+{
+    id: base
+
+    property bool expanded: false
+    property var borderWidth: 1
+    property color borderColor: "#EAEAEC"
+    property color headerBackgroundColor: "white"
+    property color headerHoverColor: "#f5f5f5"
+    property color drawerBackgroundColor: "white"
+    property alias headerItem: header.children
+    property alias drawerItem: drawer.children
+
+    width: parent.width
+    height: childrenRect.height
+
+    Rectangle
+    {
+        id: header
+        border
+        {
+            color: borderColor
+            width: borderWidth
+        }
+        color: headerMouseArea.containsMouse ? headerHoverColor : headerBackgroundColor
+        height: childrenRect.height
+        width: parent.width
+        Behavior on color
+        {
+            ColorAnimation
+            {
+                duration: 100
+            }
+        }
+    }
+
+    MouseArea
+    {
+        id: headerMouseArea
+        anchors.fill: header
+        onClicked: base.expanded = !base.expanded
+        hoverEnabled: true
+    }
+
+    Rectangle
+    {
+        id: drawer
+        anchors
+        {
+            top: header.bottom
+            topMargin: -1
+        }
+        border
+        {
+            color: borderColor
+            width: borderWidth
+        }
+        clip: true
+        color: headerBackgroundColor
+        height: base.expanded ? childrenRect.height : 0
+        width: parent.width
+        Behavior on height
+        {
+            NumberAnimation
+            {
+                duration: 100
+            }
+        }
+    }
+}

+ 63 - 0
plugins/UM3NetworkPrinting/resources/qml/MonitorBuildplateConfiguration.qml

@@ -0,0 +1,63 @@
+// Copyright (c) 2018 Ultimaker B.V.
+// Cura is released under the terms of the LGPLv3 or higher.
+
+import QtQuick 2.2
+import QtQuick.Controls 2.0
+import UM 1.3 as UM
+
+/**
+ * This component comprises a buildplate icon and the buildplate name. It is
+ * used by the MonitorPrinterConfiguration component along with two instances
+ * of MonitorExtruderConfiguration.
+ *
+ * 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
+{
+    // The buildplate name
+    property alias buildplate: buildplateLabel.text
+
+    // Height is one 18px label/icon
+    height: 18 * screenScaleFactor // TODO: Theme!
+    width: childrenRect.width
+
+    Row
+    {
+        height: parent.height
+        spacing: 12 * screenScaleFactor // TODO: Theme! (Should be same as extruder spacing)
+
+        // This wrapper ensures that the buildplate icon is located centered
+        // below an extruder icon.
+        Item
+        {
+            height: parent.height
+            width: 32 * screenScaleFactor // TODO: Theme! (Should be same as extruder icon width)
+
+            UM.RecolorImage
+            {
+                id: buildplateIcon
+                anchors.centerIn: parent
+                color: "#0a0850" // TODO: Theme! (Standard purple)
+                height: parent.height
+                source: "../svg/icons/buildplate.svg"
+                width: height
+            }
+        }
+        
+        Label
+        {
+            id: buildplateLabel
+            color: "#191919" // TODO: Theme!
+            elide: Text.ElideRight
+            font: UM.Theme.getFont("very_small") // 12pt, regular
+            text: ""
+
+            // FIXED-LINE-HEIGHT:
+            height: 18 * screenScaleFactor // TODO: Theme!
+            verticalAlignment: Text.AlignVCenter
+        }
+    }
+}

+ 76 - 0
plugins/UM3NetworkPrinting/resources/qml/MonitorExtruderConfiguration.qml

@@ -0,0 +1,76 @@
+// Copyright (c) 2018 Ultimaker B.V.
+// Cura is released under the terms of the LGPLv3 or higher.
+
+import QtQuick 2.2
+import QtQuick.Controls 2.0
+import UM 1.3 as UM
+
+/**
+ * This component comprises a colored extruder icon, the material name, and the
+ * print core name. It is used by the MonitorPrinterConfiguration component with
+ * a sibling instance as well as a MonitorBuildplateConfiguration instance.
+ *
+ * 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
+{
+    // The material color
+    property alias color: extruderIcon.color
+
+    // The extruder position; NOTE: Decent human beings count from 0
+    property alias position: extruderIcon.position
+
+    // The material name
+    property alias material: materialLabel.text
+
+    // The print core name (referred to as hotendID in Python)
+    property alias printCore: printCoreLabel.text
+
+    // Height is 2 x 18px labels, plus 4px spacing between them
+    height: 40 * screenScaleFactor // TODO: Theme!
+    width: childrenRect.width
+
+    MonitorIconExtruder
+    {
+        id: extruderIcon
+        color: "#eeeeee" // TODO: Theme!
+        position: 0
+    }
+    Label
+    {
+        id: materialLabel
+        anchors
+        {
+            left: extruderIcon.right
+            leftMargin: 12 * screenScaleFactor // TODO: Theme!
+        }
+        color: "#191919" // TODO: Theme!
+        elide: Text.ElideRight
+        font: UM.Theme.getFont("very_small") // 12pt, regular
+        text: ""
+
+        // FIXED-LINE-HEIGHT:
+        height: 18 * screenScaleFactor // TODO: Theme!
+        verticalAlignment: Text.AlignVCenter
+    }
+    Label
+    {
+        id: printCoreLabel
+        anchors
+        {
+            left: materialLabel.left
+            bottom: parent.bottom
+        }
+        color: "#191919" // TODO: Theme!
+        elide: Text.ElideRight
+        font: UM.Theme.getFont("small") // 12pt, bold
+        text: ""
+
+        // FIXED-LINE-HEIGHT:
+        height: 18 * screenScaleFactor // TODO: Theme!
+        verticalAlignment: Text.AlignVCenter
+    }
+}

+ 60 - 0
plugins/UM3NetworkPrinting/resources/qml/MonitorIconExtruder.qml

@@ -0,0 +1,60 @@
+// Copyright (c) 2018 Ultimaker B.V.
+// Cura is released under the terms of the LGPLv3 or higher.
+
+import QtQuick 2.2
+import QtQuick.Controls 2.0
+import UM 1.3 as UM
+
+/**
+ * This component is a sort of "super icon" which includes a colored SVG image
+ * as well as the extruder position number. It is used in the the
+ * MonitorExtruderConfiguration component.
+ */
+Item
+{
+    // The material color
+    property alias color: icon.color
+
+    // The extruder position; NOTE: Decent human beings count from 0
+    property int position: 0
+
+    // The extruder icon size; NOTE: This shouldn't need to be changed
+    property int size: 32 // TODO: Theme!
+
+    // THe extruder icon source; NOTE: This shouldn't need to be changed
+    property string iconSource: "../svg/icons/extruder.svg"
+
+    height: size
+    width: size
+
+    UM.RecolorImage
+    {
+        id: icon
+        anchors.fill: parent
+        source: iconSource
+        width: size
+    }
+
+    /*
+     * The label uses some "fancy" math to ensure that if you change the overall
+     * icon size, the number scales with it. That is to say, the font properties
+     * are linked to the icon size, NOT the theme. And that's intentional.
+     */
+    Label
+    {
+        id: positionLabel
+        font
+        {
+            pointSize: Math.round(size * 0.3125)
+            weight: Font.Bold
+        }
+        height: Math.round(size / 2) * screenScaleFactor
+        horizontalAlignment: Text.AlignHCenter
+        text: position + 1
+        verticalAlignment: Text.AlignVCenter
+        width: Math.round(size / 2) * screenScaleFactor
+        x: Math.round(size * 0.25) * screenScaleFactor
+        y: Math.round(size * 0.15625) * screenScaleFactor
+        // TODO: Once 'size' is themed, screenScaleFactor won't be needed
+    }
+}

+ 179 - 0
plugins/UM3NetworkPrinting/resources/qml/MonitorPrintJobCard.qml

@@ -0,0 +1,179 @@
+// Copyright (c) 2018 Ultimaker B.V.
+// Cura is released under the terms of the LGPLv3 or higher.
+
+import QtQuick 2.2
+import QtQuick.Controls 2.0
+import UM 1.3 as UM
+
+/**
+ * A Print Job Card is essentially just a filled-in Expandable Card item. All
+ * data within it is derived from being passed a printJob property.
+ *
+ * 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 print job which all other data is derived from
+    property var printJob: null
+
+    width: parent.width
+    height: childrenRect.height
+
+    ExpandableCard
+    {
+        headerItem: Row
+        {
+            height: 48 * screenScaleFactor // TODO: Theme!
+            anchors.left: parent.left
+            anchors.leftMargin: 24 * screenScaleFactor // TODO: Theme!
+            spacing: 18 * screenScaleFactor // TODO: Theme!
+
+            MonitorPrintJobPreview
+            {
+                printJob: base.printJob
+                size: 32 * screenScaleFactor // TODO: Theme!
+                anchors.verticalCenter: parent.verticalCenter
+            }
+
+            Label
+            {
+                text: printJob && printJob.name ? printJob.name : ""
+                color: "#374355"
+                elide: Text.ElideRight
+                font: UM.Theme.getFont("medium") // 14pt, regular
+                anchors.verticalCenter: parent.verticalCenter
+                width: 216 * screenScaleFactor // TODO: Theme! (Should match column size)
+
+                // FIXED-LINE-HEIGHT:
+                height: 18 * screenScaleFactor // TODO: Theme!
+                verticalAlignment: Text.AlignVCenter
+            }
+            
+            Label
+            {
+                text: printJob ? OutputDevice.formatDuration(printJob.timeTotal) : ""
+                color: "#374355"
+                elide: Text.ElideRight
+                font: UM.Theme.getFont("medium") // 14pt, regular
+                anchors.verticalCenter: parent.verticalCenter
+                width: 216 * screenScaleFactor // TODO: Theme! (Should match column size)
+
+                // FIXED-LINE-HEIGHT:
+                height: 18 * screenScaleFactor // TODO: Theme!
+                verticalAlignment: Text.AlignVCenter
+            }
+
+            Item
+            {
+                anchors.verticalCenter: parent.verticalCenter
+                height: 18 * screenScaleFactor // TODO: This should be childrenRect.height but QML throws warnings
+                width: childrenRect.width
+
+                Label
+                {
+                    id: printerAssignmentLabel
+                    anchors.verticalCenter: parent.verticalCenter
+                    color: "#374355"
+                    elide: Text.ElideRight
+                    font: UM.Theme.getFont("medium") // 14pt, regular
+                    text: {
+                        if (printJob !== null) {
+                            if (printJob.assignedPrinter == null)
+                            {
+                                if (printJob.state == "error")
+                                {
+                                    return catalog.i18nc("@label", "Unavailable printer")
+                                }
+                                return catalog.i18nc("@label", "First available")
+                            }
+                            return printJob.assignedPrinter.name
+                        }
+                        return ""
+                    }
+                    visible: printJob
+
+                    // FIXED-LINE-HEIGHT:
+                    height: 18 * screenScaleFactor // TODO: Theme!
+                    verticalAlignment: Text.AlignVCenter
+                }
+
+                Row
+                {
+                    id: printerFamilyPills
+                    anchors
+                    {
+                        left: printerAssignmentLabel.right;
+                        leftMargin: 12 // TODO: Theme!
+                        verticalCenter: parent.verticalCenter
+                    }
+                    height: childrenRect.height
+                    spacing: 6 // TODO: Theme!
+
+                    Repeater
+                    {
+                        id: compatiblePills
+                        delegate: MonitorPrinterPill
+                        {
+                            text: modelData
+                        }
+                        model: printJob ? printJob.compatibleMachineFamilies : []
+                    }
+                }
+            }
+        }
+        drawerItem: Row
+        {
+            anchors
+            {
+                left: parent.left
+                leftMargin: 74 * screenScaleFactor // TODO: Theme!
+            }
+            height: 108 * screenScaleFactor // TODO: Theme!
+            spacing: 18 * screenScaleFactor // TODO: Theme!
+
+            MonitorPrinterConfiguration
+            {
+                id: printerConfiguration
+                anchors.verticalCenter: parent.verticalCenter
+                buildplate: "Glass"
+                configurations:
+                [
+                    base.printJob.configuration.extruderConfigurations[0],
+                    base.printJob.configuration.extruderConfigurations[1]
+                ]
+                height: 72 * screenScaleFactor // TODO: Theme!
+            }
+            Label {
+                text: printJob && printJob.owner ? printJob.owner : ""
+                color: "#374355" // TODO: Theme!
+                elide: Text.ElideRight
+                font: UM.Theme.getFont("medium") // 14pt, regular
+                anchors.top: printerConfiguration.top
+
+                // FIXED-LINE-HEIGHT:
+                height: 18 * screenScaleFactor // TODO: Theme!
+                verticalAlignment: Text.AlignVCenter
+            }
+        }
+    }
+
+    PrintJobContextMenu
+    {
+        id: contextButton
+        anchors
+        {
+            right: parent.right;
+            rightMargin: 8 * screenScaleFactor // TODO: Theme!
+            top: parent.top
+            topMargin: 8 * screenScaleFactor // TODO: Theme!
+        }
+        printJob: base.printJob
+        width: 32 * screenScaleFactor // TODO: Theme!
+        height: 32 * screenScaleFactor // TODO: Theme!
+    }
+}

+ 63 - 0
plugins/UM3NetworkPrinting/resources/qml/MonitorPrintJobPreview.qml

@@ -0,0 +1,63 @@
+// Copyright (c) 2018 Ultimaker B.V.
+// Cura is released under the terms of the LGPLv3 or higher.
+
+import QtQuick 2.2
+import QtQuick.Controls 2.0
+import UM 1.3 as UM
+
+// TODO: Documentation!
+Item
+{
+    id: printJobPreview
+
+    property var printJob: null
+    property var size: 256
+
+    width: size
+    height: size
+
+    // Actual content
+    Image
+    {
+        id: previewImage
+        anchors.fill: parent
+        opacity: printJob && printJob.state == "error" ? 0.5 : 1.0
+        source: printJob ? printJob.previewImageUrl : ""
+        visible: printJob
+    }
+
+    UM.RecolorImage
+    {
+        id: ultiBotImage
+        
+        anchors.centerIn: printJobPreview
+        color: UM.Theme.getColor("monitor_placeholder_image")
+        height: printJobPreview.height
+        source: "../svg/ultibot.svg"
+        sourceSize
+        {
+            height: height
+            width: width
+        }
+        /* Since print jobs ALWAYS have an image url, we have to check if that image URL errors or
+            not in order to determine if we show the placeholder (ultibot) image instead. */
+        visible: printJob && previewImage.status == Image.Error
+        width: printJobPreview.width
+    }
+
+    UM.RecolorImage
+    {
+        id: statusImage
+        anchors.centerIn: printJobPreview
+        color: UM.Theme.getColor("monitor_image_overlay")
+        height: 0.5 * printJobPreview.height
+        source: printJob && printJob.state == "error" ? "../svg/aborted-icon.svg" : ""
+        sourceSize
+        {
+            height: height
+            width: width
+        }
+        visible: source != ""
+        width: 0.5 * printJobPreview.width
+    }
+}

+ 58 - 0
plugins/UM3NetworkPrinting/resources/qml/MonitorPrinterConfiguration.qml

@@ -0,0 +1,58 @@
+// Copyright (c) 2018 Ultimaker B.V.
+// Cura is released under the terms of the LGPLv3 or higher.
+
+import QtQuick 2.2
+import QtQuick.Controls 2.0
+import UM 1.3 as UM
+
+/**
+ * The MonitorPrinterConfiguration accepts 2 configuration objects as input and
+ * applies them to a MonitorBuildplateConfiguration instance and two instances
+ * of MonitorExtruderConfiguration. It's used in both the MonitorPrintJobCard
+ * component as well as the MonitorPrinterCard component.
+ */
+Item
+{
+    id: base
+
+    // Extracted buildplate configuration
+    property alias buildplate: buildplateConfig.buildplate
+
+    // Array of extracted extruder configurations
+    property var configurations: null
+
+    // Default size, but should be stretched to fill parent
+    height: 72 * parent.height
+    width: 450 * screenScaleFactor // TODO: Theme!
+
+    Row
+    {
+        id: extruderConfigurationRow
+        spacing: 18 * screenScaleFactor // TODO: Theme!
+
+        Repeater
+        {
+            id: extruderConfigurationRepeater
+            model: configurations
+
+            MonitorExtruderConfiguration
+            {
+                color: modelData.activeMaterial ? modelData.activeMaterial.color : "#eeeeee" // TODO: Theme!
+                material: modelData.activeMaterial ? modelData.activeMaterial.name : ""
+                position: modelData.position
+                printCore: modelData.hotendID
+
+                // Keep things responsive!
+                width: Math.floor((base.width - (configurations.length - 1) * extruderConfigurationRow.spacing) / configurations.length)
+            }
+
+        }
+    }
+
+    MonitorBuildplateConfiguration
+    {
+        id: buildplateConfig
+        anchors.bottom: parent.bottom
+        buildplate: "Glass" // 'Glass' as a default
+    }
+}

+ 34 - 0
plugins/UM3NetworkPrinting/resources/qml/MonitorPrinterPill.qml

@@ -0,0 +1,34 @@
+// Copyright (c) 2018 Ultimaker B.V.
+// Cura is released under the terms of the LGPLv3 or higher.
+
+import QtQuick 2.2
+import QtQuick.Controls 1.4
+import UM 1.2 as UM
+
+/**
+ * A MonitorPrinterPill is a blue-colored tag indicating which printers a print
+ * job is compatible with. It is used by the MonitorPrintJobCard component.
+ */
+Item
+{
+    // The printer name
+    property alias text: printerNameLabel.text;
+
+    implicitHeight: 18 * screenScaleFactor // TODO: Theme!
+    implicitWidth: printerNameLabel.contentWidth + 12 // TODO: Theme!
+
+    Rectangle {
+        id: background
+        anchors.fill: parent
+        color: "#e4e4f2" // TODO: Theme!
+        radius: 2 * screenScaleFactor // TODO: Theme!
+    }
+
+    Label {
+        id: printerNameLabel
+        anchors.centerIn: parent
+        color: "#535369" // TODO: Theme!
+        text: ""
+        font.pointSize: 10
+    }
+}

+ 5 - 0
plugins/UM3NetworkPrinting/resources/svg/icons/buildplate.svg

@@ -0,0 +1,5 @@
+<svg width="18px" height="18px" viewBox="0 0 18 18" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
+    <g id="Page-1" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
+        <path d="M18,5 L18,6 L9,10 L0,6 L0,5 L9,1 L18,5 Z M18,8.18863507 L9,12.1886351 L0,8.18863507 L0,7.09431753 L9,11.0943175 L18,7.09431753 L18,8.18863507 Z M18,10.3772701 L9,14.3772701 L0,10.3772701 L0,9.2829526 L9,13.2829526 L18,9.2829526 L18,10.3772701 Z M18,12.5659052 L9,16.5659052 L0,12.5659052 L0,11.4715877 L9,15.4715877 L18,11.4715877 L18,12.5659052 Z" id="Combined-Shape" fill="#D10000" fill-rule="nonzero"></path>
+    </g>
+</svg>

Some files were not shown because too many files changed in this diff