diff --git a/cura/CameraImageProvider.py b/cura/CameraImageProvider.py
new file mode 100644
index 0000000000..ff66170f3c
--- /dev/null
+++ b/cura/CameraImageProvider.py
@@ -0,0 +1,18 @@
+from PyQt5.QtGui import QImage
+from PyQt5.QtQuick import QQuickImageProvider
+from PyQt5.QtCore import QSize
+
+from UM.Application import Application
+
+class CameraImageProvider(QQuickImageProvider):
+ def __init__(self):
+ QQuickImageProvider.__init__(self, QQuickImageProvider.Image)
+
+ ## Request a new image.
+ def requestImage(self, id, size):
+ for output_device in Application.getInstance().getOutputDeviceManager().getOutputDevices():
+ try:
+ return output_device.getCameraImage(), QSize(15, 15)
+ except AttributeError:
+ pass
+ return QImage(), QSize(15, 15)
\ No newline at end of file
diff --git a/cura/CuraApplication.py b/cura/CuraApplication.py
index 6d0f609c6d..9d068d1214 100644
--- a/cura/CuraApplication.py
+++ b/cura/CuraApplication.py
@@ -44,6 +44,7 @@ from . import ZOffsetDecorator
from . import CuraSplashScreen
from . import MachineManagerModel
from . import ContainerSettingsModel
+from . import CameraImageProvider
from . import MachineActionManager
from PyQt5.QtCore import pyqtSlot, QUrl, pyqtSignal, pyqtProperty, QEvent, Q_ENUMS
@@ -229,7 +230,7 @@ class CuraApplication(QtApplication):
JobQueue.getInstance().jobFinished.connect(self._onJobFinished)
self.applicationShuttingDown.connect(self.saveSettings)
-
+ self.engineCreatedSignal.connect(self._onEngineCreated)
self._recent_files = []
files = Preferences.getInstance().getValue("cura/recent_files").split(";")
for f in files:
@@ -238,6 +239,9 @@ class CuraApplication(QtApplication):
self._recent_files.append(QUrl.fromLocalFile(f))
+ def _onEngineCreated(self):
+ self._engine.addImageProvider("camera", CameraImageProvider.CameraImageProvider())
+
## Cura has multiple locations where instance containers need to be saved, so we need to handle this differently.
#
# Note that the AutoSave plugin also calls this method.
diff --git a/cura/PrinterOutputDevice.py b/cura/PrinterOutputDevice.py
index 7649106523..7f6e51e1fd 100644
--- a/cura/PrinterOutputDevice.py
+++ b/cura/PrinterOutputDevice.py
@@ -29,6 +29,10 @@ class PrinterOutputDevice(QObject, OutputDevice):
self._head_y = 0
self._head_z = 0
self._connection_state = ConnectionState.closed
+ self._time_elapsed = 0
+ self._time_total = 0
+ self._job_state = ""
+ self._job_name = ""
def requestWrite(self, node, file_name = None, filter_by_machine = False):
raise NotImplementedError("requestWrite needs to be implemented")
@@ -57,6 +61,39 @@ class PrinterOutputDevice(QObject, OutputDevice):
# it also sends it's own device_id (for convenience sake)
connectionStateChanged = pyqtSignal(str)
+ timeElapsedChanged = pyqtSignal()
+
+ timeTotalChanged = pyqtSignal()
+
+ jobStateChanged = pyqtSignal()
+
+ jobNameChanged = pyqtSignal()
+
+ @pyqtProperty(str, notify = jobStateChanged)
+ def jobState(self):
+ return self._job_state
+
+ def _updateJobState(self, job_state):
+ if self._job_state != job_state:
+ self._job_state = job_state
+ self.jobStateChanged.emit()
+
+ @pyqtSlot(str)
+ def setJobState(self, job_state):
+ self._setJobState(job_state)
+
+ def _setJobState(self, job_state):
+ Logger.log("w", "_setJobState is not implemented by this output device")
+
+ @pyqtProperty(str, notify = jobNameChanged)
+ def jobName(self):
+ return self._job_name
+
+ def setJobName(self, name):
+ if self._job_name != name:
+ self._job_name = name
+ self.jobNameChanged.emit()
+
## Get the bed temperature of the bed (if any)
# This function is "final" (do not re-implement)
# /sa _getBedTemperature implementation function
@@ -74,6 +111,30 @@ class PrinterOutputDevice(QObject, OutputDevice):
self._target_bed_temperature = temperature
self.targetBedTemperatureChanged.emit()
+ ## Time the print has been printing.
+ # Note that timeTotal - timeElapsed should give time remaining.
+ @pyqtProperty(float, notify = timeElapsedChanged)
+ def timeElapsed(self):
+ return self._time_elapsed
+
+ ## Total time of the print
+ # Note that timeTotal - timeElapsed should give time remaining.
+ @pyqtProperty(float, notify=timeTotalChanged)
+ def timeTotal(self):
+ return self._time_total
+
+ @pyqtSlot(float)
+ def setTimeTotal(self, new_total):
+ if self._time_total != new_total:
+ self._time_total = new_total
+ self.timeTotalChanged.emit()
+
+ @pyqtSlot(float)
+ def setTimeElapsed(self, time_elapsed):
+ if self._time_elapsed != time_elapsed:
+ self._time_elapsed = time_elapsed
+ self.timeElapsedChanged.emit()
+
## Home the head of the connected printer
# This function is "final" (do not re-implement)
# /sa _homeHead implementation function
diff --git a/resources/qml/Cura.qml b/resources/qml/Cura.qml
index ef26218332..c1990d432e 100644
--- a/resources/qml/Cura.qml
+++ b/resources/qml/Cura.qml
@@ -16,7 +16,7 @@ UM.MainWindow
//: Cura application window title
title: catalog.i18nc("@title:window","Cura");
viewportRect: Qt.rect(0, 0, (base.width - sidebar.width) / base.width, 1.0)
-
+ property bool monitoringPrint: false
Component.onCompleted:
{
Printer.setMinimumWindowSize(UM.Theme.getSize("window_minimum_size"))
@@ -536,9 +536,46 @@ UM.MainWindow
bottom: parent.bottom;
right: parent.right;
}
-
+ onMonitoringPrintChanged: base.monitoringPrint = monitoringPrint
width: UM.Theme.getSize("sidebar").width;
}
+
+ Rectangle
+ {
+ id: viewportOverlay
+
+ color: UM.Theme.getColor("viewport_overlay")
+ anchors
+ {
+ top: parent.top
+ bottom: parent.bottom
+ left:parent.left
+ right: sidebar.left
+ }
+ visible: opacity > 0
+ opacity: base.monitoringPrint ? 0.75 : 0
+
+ Behavior on opacity { NumberAnimation { duration: 100; } }
+
+ MouseArea {
+ anchors.fill: parent
+ acceptedButtons: Qt.AllButtons
+
+ onWheel: wheel.accepted = true
+ }
+ }
+
+ Image
+ {
+ id: cameraImage
+ width: Math.min(viewportOverlay.width, sourceSize.width)
+ height: sourceSize.height * width / sourceSize.width
+ anchors.horizontalCenter: parent.horizontalCenter
+ anchors.verticalCenter: parent.verticalCenter
+ anchors.horizontalCenterOffset: - UM.Theme.getSize("sidebar").width / 2
+ visible: base.monitoringPrint
+ source: Cura.MachineManager.printerOutputDevices.length > 0 ? Cura.MachineManager.printerOutputDevices[0].cameraImage : ""
+ }
}
}
diff --git a/resources/qml/MonitorButton.qml b/resources/qml/MonitorButton.qml
new file mode 100644
index 0000000000..ca6b216a0a
--- /dev/null
+++ b/resources/qml/MonitorButton.qml
@@ -0,0 +1,183 @@
+// Copyright (c) 2016 Ultimaker B.V.
+// Cura is released under the terms of the AGPLv3 or higher.
+
+import QtQuick 2.2
+import QtQuick.Controls 1.1
+import QtQuick.Controls.Styles 1.1
+import QtQuick.Layouts 1.1
+
+import UM 1.1 as UM
+import Cura 1.0 as Cura
+
+Rectangle
+{
+ id: base;
+ UM.I18nCatalog { id: catalog; name:"cura"}
+
+ property bool printerConnected: Cura.MachineManager.printerOutputDevices.length != 0
+ property real progress: printerConnected ? Cura.MachineManager.printerOutputDevices[0].progress : 0;
+ property int backendState: UM.Backend.state;
+
+ property bool activity: Printer.getPlatformActivity;
+ property int totalHeight: childrenRect.height + UM.Theme.getSize("default_margin").height
+ property string fileBaseName
+ property string statusText:
+ {
+ if(!printerConnected)
+ {
+ return "Please check your printer connections"
+ } else if(Cura.MachineManager.printerOutputDevices[0].jobState == "printing")
+ {
+ return "Printing..."
+ } else if(Cura.MachineManager.printerOutputDevices[0].jobState == "paused")
+ {
+ return "Paused"
+ }
+ else if(Cura.MachineManager.printerOutputDevices[0].jobState == "pre_print")
+ {
+ return "Preparing..."
+ }
+ else
+ {
+ return " "
+ }
+
+ }
+
+ Label
+ {
+ id: statusLabel
+ width: parent.width - 2 * UM.Theme.getSize("default_margin").width
+ anchors.top: parent.top
+ anchors.left: parent.left
+ anchors.leftMargin: UM.Theme.getSize("default_margin").width
+
+ color: printerConnected ? Cura.MachineManager.printerOutputDevices[0].jobState == "paused" ? UM.Theme.getColor("status_paused") : UM.Theme.getColor("status_ready") : UM.Theme.getColor("status_offline")
+ font: UM.Theme.getFont("large")
+ text: statusText;
+ }
+
+ Label
+ {
+ id: percentageLabel
+ anchors.top: parent.top
+ anchors.right: progressBar.right
+
+ color: printerConnected ? Cura.MachineManager.printerOutputDevices[0].jobState == "paused" ? UM.Theme.getColor("status_paused") : UM.Theme.getColor("status_ready") : UM.Theme.getColor("status_offline")
+ font: UM.Theme.getFont("large")
+ text: Math.round(progress * 100) + "%";
+ visible: printerConnected
+ }
+
+ Rectangle
+ {
+ id: progressBar
+ width: parent.width - 2 * UM.Theme.getSize("default_margin").width
+ height: UM.Theme.getSize("progressbar").height
+ anchors.top: statusLabel.bottom
+ anchors.topMargin: UM.Theme.getSize("default_margin").height / 4
+ anchors.left: parent.left
+ anchors.leftMargin: UM.Theme.getSize("default_margin").width
+ radius: UM.Theme.getSize("progressbar_radius").width
+ color: UM.Theme.getColor("progressbar_background")
+
+ Rectangle
+ {
+ width: Math.max(parent.width * base.progress)
+ height: parent.height
+ color: printerConnected ? Cura.MachineManager.printerOutputDevices[0].jobState == "paused" ? UM.Theme.getColor("status_paused") : UM.Theme.getColor("status_ready") : UM.Theme.getColor("status_offline")
+ radius: UM.Theme.getSize("progressbar_radius").width
+ }
+ }
+
+ Button
+ {
+ id: abortButton
+
+ visible: printerConnected
+ height: UM.Theme.getSize("save_button_save_to_button").height
+
+ anchors.top: progressBar.bottom
+ anchors.topMargin: UM.Theme.getSize("default_margin").height
+ anchors.right: parent.right
+ anchors.rightMargin: UM.Theme.getSize("default_margin").width
+
+ text: catalog.i18nc("@label:", "Abort Print")
+ onClicked: { Cura.MachineManager.printerOutputDevices[0].setJobState("abort") }
+
+
+ style: ButtonStyle
+ {
+ background: Rectangle
+ {
+ border.width: UM.Theme.getSize("default_lining").width
+ border.color: !control.enabled ? UM.Theme.getColor("action_button_disabled_border") :
+ control.pressed ? UM.Theme.getColor("action_button_active_border") :
+ control.hovered ? UM.Theme.getColor("action_button_hovered_border") : UM.Theme.getColor("action_button_border")
+ color: !control.enabled ? UM.Theme.getColor("action_button_disabled") :
+ control.pressed ? UM.Theme.getColor("action_button_active") :
+ control.hovered ? UM.Theme.getColor("action_button_hovered") : UM.Theme.getColor("action_button")
+ Behavior on color { ColorAnimation { duration: 50; } }
+
+ implicitWidth: actualLabel.contentWidth + (UM.Theme.getSize("default_margin").width * 2)
+
+ Label
+ {
+ id: actualLabel
+ anchors.centerIn: parent
+ color: !control.enabled ? UM.Theme.getColor("action_button_disabled_text") :
+ control.pressed ? UM.Theme.getColor("action_button_active_text") :
+ control.hovered ? UM.Theme.getColor("action_button_hovered_text") : UM.Theme.getColor("action_button_text")
+ font: UM.Theme.getFont("action_button")
+ text: control.text;
+ }
+ }
+ label: Item { }
+ }
+ }
+
+ Button
+ {
+ id: pauseButton
+
+ height: UM.Theme.getSize("save_button_save_to_button").height
+ visible: printerConnected
+
+ anchors.top: progressBar.bottom
+ anchors.topMargin: UM.Theme.getSize("default_margin").height
+ anchors.right: abortButton.left
+ anchors.rightMargin: UM.Theme.getSize("default_margin").width
+
+ text: printerConnected ? Cura.MachineManager.printerOutputDevices[0].jobState == "paused" ? catalog.i18nc("@label:", "Resume") : catalog.i18nc("@label:", "Pause") : ""
+ onClicked: { Cura.MachineManager.printerOutputDevices[0].jobState == "paused" ? Cura.MachineManager.printerOutputDevices[0].setJobState("print") : Cura.MachineManager.printerOutputDevices[0].setJobState("pause") }
+
+ style: ButtonStyle
+ {
+ background: Rectangle
+ {
+ border.width: UM.Theme.getSize("default_lining").width
+ border.color: !control.enabled ? UM.Theme.getColor("action_button_disabled_border") :
+ control.pressed ? UM.Theme.getColor("action_button_active_border") :
+ control.hovered ? UM.Theme.getColor("action_button_hovered_border") : UM.Theme.getColor("action_button_border")
+ color: !control.enabled ? UM.Theme.getColor("action_button_disabled") :
+ control.pressed ? UM.Theme.getColor("action_button_active") :
+ control.hovered ? UM.Theme.getColor("action_button_hovered") : UM.Theme.getColor("action_button")
+ Behavior on color { ColorAnimation { duration: 50; } }
+
+ implicitWidth: actualLabel.contentWidth + (UM.Theme.getSize("default_margin").width * 2)
+
+ Label
+ {
+ id: actualLabel
+ anchors.centerIn: parent
+ color: !control.enabled ? UM.Theme.getColor("action_button_disabled_text") :
+ control.pressed ? UM.Theme.getColor("action_button_active_text") :
+ control.hovered ? UM.Theme.getColor("action_button_hovered_text") : UM.Theme.getColor("action_button_text")
+ font: UM.Theme.getFont("action_button")
+ text: control.text;
+ }
+ }
+ label: Item { }
+ }
+ }
+}
diff --git a/resources/qml/Sidebar.qml b/resources/qml/Sidebar.qml
index 4c8d671a7f..e1516214f1 100644
--- a/resources/qml/Sidebar.qml
+++ b/resources/qml/Sidebar.qml
@@ -6,7 +6,7 @@ import QtQuick.Controls 1.1
import QtQuick.Controls.Styles 1.1
import QtQuick.Layouts 1.1
-import UM 1.1 as UM
+import UM 1.2 as UM
import Cura 1.0 as Cura
Rectangle
@@ -14,6 +14,7 @@ Rectangle
id: base;
property int currentModeIndex;
+ property bool monitoringPrint: false
// Is there an output device for this printer?
property bool printerConnected: Cura.MachineManager.printerOutputDevices.length != 0
@@ -21,6 +22,7 @@ Rectangle
color: UM.Theme.getColor("sidebar");
UM.I18nCatalog { id: catalog; name:"cura"}
+
function showTooltip(item, position, text)
{
tooltip.text = text;
@@ -33,6 +35,22 @@ Rectangle
tooltip.hide();
}
+ function strPadLeft(string, pad, length) {
+ return (new Array(length + 1).join(pad) + string).slice(-length);
+ }
+
+ function getPrettyTime(time)
+ {
+ var hours = Math.floor(time / 3600)
+ time -= hours * 3600
+ var minutes = Math.floor(time / 60);
+ time -= minutes * 60
+ var seconds = Math.floor(time);
+
+ var finalTime = strPadLeft(hours, "0", 2) + ':' + strPadLeft(minutes,'0',2)+ ':' + strPadLeft(seconds,'0',2);
+ return finalTime;
+ }
+
MouseArea
{
anchors.fill: parent
@@ -44,12 +62,64 @@ Rectangle
}
}
+ // Mode selection buttons for changing between Setting & Monitor print mode
+ Rectangle
+ {
+ id: sidebarHeaderBar
+ anchors.left: parent.left
+ anchors.right: parent.right
+ height: childrenRect.height
+ color: UM.Theme.getColor("sidebar_header_bar")
+
+ Row
+ {
+ anchors.left: parent.left
+ anchors.leftMargin: UM.Theme.getSize("default_margin").width;
+ anchors.right: parent.right
+ Button
+ {
+ width: (parent.width - UM.Theme.getSize("default_margin").width) / 2
+ height: UM.Theme.getSize("sidebar_header").height
+ onClicked: monitoringPrint = false
+ iconSource: UM.Theme.getIcon("tab_settings");
+ checkable: true
+ checked: true
+ exclusiveGroup: sidebarHeaderBarGroup
+
+ style: UM.Theme.styles.sidebar_header_tab
+ }
+ Button
+ {
+ width: (parent.width - UM.Theme.getSize("default_margin").width) / 2
+ height: UM.Theme.getSize("sidebar_header").height
+ onClicked: monitoringPrint = true
+ iconSource: {
+ if(!printerConnected)
+ {
+ return UM.Theme.getIcon("tab_monitor")
+ } else if(Cura.MachineManager.printerOutputDevices[0].jobState == "paused")
+ {
+ return UM.Theme.getIcon("tab_monitor_paused")
+ } else if (Cura.MachineManager.printerOutputDevices[0].jobState != "error")
+ {
+ return UM.Theme.getIcon("tab_monitor_connected")
+ }
+ }
+ checkable: true
+ exclusiveGroup: sidebarHeaderBarGroup
+
+ style: UM.Theme.styles.sidebar_header_tab
+ }
+ ExclusiveGroup { id: sidebarHeaderBarGroup }
+ }
+ }
+
SidebarHeader {
id: header
width: parent.width
height: totalHeightHeader
- anchors.top: parent.top
+ anchors.top: sidebarHeaderBar.bottom
anchors.topMargin: UM.Theme.getSize("default_margin").height
onShowTooltip: base.showTooltip(item, location, text)
@@ -85,14 +155,15 @@ Rectangle
Label {
id: settingsModeLabel
- text: catalog.i18nc("@label:listbox","Setup");
+ text: catalog.i18nc("@label:listbox","Print Setup");
anchors.left: parent.left
anchors.leftMargin: UM.Theme.getSize("default_margin").width;
anchors.top: headerSeparator.bottom
anchors.topMargin: UM.Theme.getSize("default_margin").height
width: parent.width/100*45
- font: UM.Theme.getFont("large");
+ font: UM.Theme.getFont("large")
color: UM.Theme.getColor("text")
+ visible: !monitoringPrint
}
Rectangle {
@@ -103,6 +174,7 @@ Rectangle
anchors.rightMargin: UM.Theme.getSize("default_margin").width
anchors.top: headerSeparator.bottom
anchors.topMargin: UM.Theme.getSize("default_margin").height
+ visible: !monitoringPrint
Component{
id: wizardDelegate
Button {
@@ -152,6 +224,19 @@ Rectangle
}
}
+ Label {
+ id: monitorLabel
+ text: catalog.i18nc("@label","Printer Monitor");
+ anchors.left: parent.left
+ anchors.leftMargin: UM.Theme.getSize("default_margin").width;
+ anchors.top: headerSeparator.bottom
+ anchors.topMargin: UM.Theme.getSize("default_margin").height
+ width: parent.width/100*45
+ font: UM.Theme.getFont("large")
+ color: UM.Theme.getColor("text")
+ visible: monitoringPrint
+ }
+
StackView
{
id: sidebarContents
@@ -161,6 +246,7 @@ Rectangle
anchors.topMargin: UM.Theme.getSize("default_margin").height
anchors.left: base.left
anchors.right: base.right
+ visible: !monitoringPrint
delegate: StackViewDelegate
{
@@ -191,23 +277,152 @@ Rectangle
}
}
- Rectangle {
+ // Item that shows the print monitor properties
+ Column
+ {
+ id: printMonitor
+
+ anchors.bottom: footerSeparator.top
+ anchors.top: monitorLabel.bottom
+ anchors.topMargin: UM.Theme.getSize("default_margin").height
+ anchors.left: base.left
+ anchors.leftMargin: UM.Theme.getSize("default_margin").width
+ anchors.right: base.right
+ visible: monitoringPrint
+
+ Loader
+ {
+ sourceComponent: monitorSection
+ property string label: catalog.i18nc("@label", "Temperatures")
+ }
+ Repeater
+ {
+ model: machineExtruderCount.properties.value
+ delegate: Loader
+ {
+ sourceComponent: monitorItem
+ property string label: machineExtruderCount.properties.value > 1 ? catalog.i18nc("@label", "Hotend Temperature %1").arg(index + 1) : catalog.i18nc("@label", "Hotend Temperature")
+ property string value: printerConnected ? Math.round(Cura.MachineManager.printerOutputDevices[0].hotendTemperatures[index]) + "°C" : ""
+ }
+ }
+ Repeater
+ {
+ model: machineHeatedBed.properties.value == "True" ? 1 : 0
+ delegate: Loader
+ {
+ sourceComponent: monitorItem
+ property string label: catalog.i18nc("@label", "Bed Temperature")
+ property string value: printerConnected ? Math.round(Cura.MachineManager.printerOutputDevices[0].bedTemperature) + "°C" : ""
+ }
+ }
+
+ Loader
+ {
+ sourceComponent: monitorSection
+ property string label: catalog.i18nc("@label", "Active print")
+ }
+ Loader
+ {
+ sourceComponent: monitorItem
+ property string label: catalog.i18nc("@label", "Job Name")
+ property string value: printerConnected ? Cura.MachineManager.printerOutputDevices[0].jobName : ""
+ }
+ Loader
+ {
+ sourceComponent: monitorItem
+ property string label: catalog.i18nc("@label", "Printing Time")
+ property string value: printerConnected ? getPrettyTime(Cura.MachineManager.printerOutputDevices[0].timeTotal) : ""
+ }
+ Loader
+ {
+ sourceComponent: monitorItem
+ property string label: catalog.i18nc("@label", "Estimated time left")
+ property string value: printerConnected ? getPrettyTime(Cura.MachineManager.printerOutputDevices[0].timeTotal - Cura.MachineManager.printerOutputDevices[0].timeElapsed) : ""
+ }
+ Loader
+ {
+ sourceComponent: monitorItem
+ property string label: catalog.i18nc("@label", "Current Layer")
+ property string value: printerConnected ? "0" : ""
+ }
+
+ Component
+ {
+ id: monitorItem
+
+ Row
+ {
+ height: UM.Theme.getSize("setting_control").height
+ Label
+ {
+ text: label
+ color: printerConnected ? UM.Theme.getColor("setting_control_text") : UM.Theme.getColor("setting_control_disabled_text")
+ font: UM.Theme.getFont("default")
+ width: base.width * 0.4
+ elide: Text.ElideRight
+ anchors.verticalCenter: parent.verticalCenter
+ }
+ Label
+ {
+ text: value
+ color: printerConnected ? UM.Theme.getColor("setting_control_text") : UM.Theme.getColor("setting_control_disabled_text")
+ font: UM.Theme.getFont("default")
+ anchors.verticalCenter: parent.verticalCenter
+ }
+ }
+ }
+ Component
+ {
+ id: monitorSection
+
+ Rectangle
+ {
+ color: UM.Theme.getColor("setting_category")
+ width: base.width - 2 * UM.Theme.getSize("default_margin").width
+ height: UM.Theme.getSize("section").height
+
+ Label
+ {
+ anchors.verticalCenter: parent.verticalCenter
+ anchors.left: parent.left
+ anchors.leftMargin: UM.Theme.getSize("default_margin").width
+ text: label
+ font: UM.Theme.getFont("setting_category")
+ color: UM.Theme.getColor("setting_category_text")
+ }
+ }
+ }
+ }
+
+ Rectangle
+ {
id: footerSeparator
width: parent.width
height: UM.Theme.getSize("sidebar_lining").height
color: UM.Theme.getColor("sidebar_lining")
anchors.bottom: saveButton.top
- anchors.bottomMargin: UM.Theme.getSize("default_margin").height
+ anchors.bottomMargin: UM.Theme.getSize("default_margin").height
}
SaveButton
{
- id: saveButton;
+ id: saveButton
implicitWidth: base.width
implicitHeight: totalHeight
anchors.bottom: parent.bottom
+ visible: !monitoringPrint
}
+ MonitorButton
+ {
+ id: monitorButton
+ implicitWidth: base.width
+ implicitHeight: totalHeight
+ anchors.bottom: parent.bottom
+ visible: monitoringPrint
+ }
+
+
SidebarTooltip
{
id: tooltip;
@@ -242,4 +457,24 @@ Rectangle
modesListModel.append({ text: catalog.i18nc("@title:tab", "Advanced"), item: sidebarAdvanced })
sidebarContents.push({ "item": modesListModel.get(base.currentModeIndex).item, "immediate": true });
}
-}
+
+ UM.SettingPropertyProvider
+ {
+ id: machineExtruderCount
+
+ containerStackId: Cura.MachineManager.activeMachineId
+ key: "machine_extruder_count"
+ watchedProperties: [ "value" ]
+ storeIndex: 0
+ }
+
+ UM.SettingPropertyProvider
+ {
+ id: machineHeatedBed
+
+ containerStackId: Cura.MachineManager.activeMachineId
+ key: "machine_heated_bed"
+ watchedProperties: [ "value" ]
+ storeIndex: 0
+ }
+}
\ No newline at end of file
diff --git a/resources/themes/cura/icons/tab_monitor.svg b/resources/themes/cura/icons/tab_monitor.svg
new file mode 100644
index 0000000000..516191b988
--- /dev/null
+++ b/resources/themes/cura/icons/tab_monitor.svg
@@ -0,0 +1,75 @@
+
+
diff --git a/resources/themes/cura/icons/tab_monitor_busy.svg b/resources/themes/cura/icons/tab_monitor_busy.svg
new file mode 100644
index 0000000000..f0e47b91d4
--- /dev/null
+++ b/resources/themes/cura/icons/tab_monitor_busy.svg
@@ -0,0 +1,107 @@
+
+
diff --git a/resources/themes/cura/icons/tab_monitor_connected.svg b/resources/themes/cura/icons/tab_monitor_connected.svg
new file mode 100644
index 0000000000..8f6f83fe91
--- /dev/null
+++ b/resources/themes/cura/icons/tab_monitor_connected.svg
@@ -0,0 +1,95 @@
+
+
diff --git a/resources/themes/cura/icons/tab_monitor_offline.svg b/resources/themes/cura/icons/tab_monitor_offline.svg
new file mode 100644
index 0000000000..a13a7b586e
--- /dev/null
+++ b/resources/themes/cura/icons/tab_monitor_offline.svg
@@ -0,0 +1,94 @@
+
+
diff --git a/resources/themes/cura/icons/tab_monitor_paused.svg b/resources/themes/cura/icons/tab_monitor_paused.svg
new file mode 100644
index 0000000000..49c8babebd
--- /dev/null
+++ b/resources/themes/cura/icons/tab_monitor_paused.svg
@@ -0,0 +1,103 @@
+
+
diff --git a/resources/themes/cura/icons/tab_monitor_stopped.svg b/resources/themes/cura/icons/tab_monitor_stopped.svg
new file mode 100644
index 0000000000..7f861067dd
--- /dev/null
+++ b/resources/themes/cura/icons/tab_monitor_stopped.svg
@@ -0,0 +1,94 @@
+
+
diff --git a/resources/themes/cura/icons/tab_settings.svg b/resources/themes/cura/icons/tab_settings.svg
new file mode 100644
index 0000000000..f181147d98
--- /dev/null
+++ b/resources/themes/cura/icons/tab_settings.svg
@@ -0,0 +1,75 @@
+
+
diff --git a/resources/themes/cura/styles.qml b/resources/themes/cura/styles.qml
index 3fdc7c896e..8d813bc2b5 100644
--- a/resources/themes/cura/styles.qml
+++ b/resources/themes/cura/styles.qml
@@ -44,6 +44,56 @@ QtObject {
}
}
+ property Component sidebar_header_tab: Component {
+ ButtonStyle {
+ background: Item {
+ implicitWidth: Theme.getSize("button").width;
+ implicitHeight: Theme.getSize("button").height;
+
+ Rectangle {
+ id: buttonFace;
+
+ anchors.fill: parent;
+ property bool down: control.pressed || (control.checkable && control.checked);
+
+ color: {
+ if(control.pressed || (control.checkable && control.checked)) {
+ return Theme.getColor("sidebar_header_active");
+ } else if(control.hovered) {
+ return Theme.getColor("sidebar_header_hover");
+ } else {
+ return Theme.getColor("sidebar_header_bar");
+ }
+ }
+ Behavior on color { ColorAnimation { duration: 50; } }
+
+ Rectangle {
+ id: underline;
+
+ anchors.left: parent.left
+ anchors.right: parent.right
+ anchors.bottom: parent.bottom
+ height: UM.Theme.getSize("sidebar_header_highlight").height
+ color: control.checked ? UM.Theme.getColor("sidebar_header_highlight") : UM.Theme.getColor("sidebar_header_highlight_hover")
+ visible: control.hovered || control.checked
+ }
+ }
+ }
+
+ label: Item {
+ Image {
+ anchors.centerIn: parent;
+ opacity: !control.enabled ? 0.2 : 1.0
+ source: control.iconSource;
+ width: Theme.getSize("button_icon").width;
+ height: Theme.getSize("button_icon").height;
+
+ sourceSize: Theme.getSize("button_icon")
+ }
+ }
+ }
+ }
+
property Component tool_button: Component {
ButtonStyle {
background: Item {
diff --git a/resources/themes/cura/theme.json b/resources/themes/cura/theme.json
index 595d0b95c2..5bc5e99765 100644
--- a/resources/themes/cura/theme.json
+++ b/resources/themes/cura/theme.json
@@ -38,6 +38,7 @@
"colors": {
"sidebar": [255, 255, 255, 255],
"lining": [127, 127, 127, 255],
+ "viewport_overlay": [24, 41, 77, 255],
"primary": [12, 169, 227, 255],
"primary_hover": [48, 182, 231, 255],
@@ -55,6 +56,10 @@
"error": [255, 140, 0, 255],
"sidebar_header_bar": [24, 41, 77, 255],
+ "sidebar_header_active": [70, 84, 113, 255],
+ "sidebar_header_hover": [24, 41, 77, 255],
+ "sidebar_header_highlight": [12, 169, 227, 255],
+ "sidebar_header_highlight_hover": [255, 255, 255, 255],
"sidebar_lining": [245, 245, 245, 255],
"button": [24, 41, 77, 255],
@@ -153,7 +158,13 @@
"message_text": [32, 166, 219, 255],
"message_dismiss": [127, 127, 127, 255],
- "tool_panel_background": [255, 255, 255, 255]
+ "tool_panel_background": [255, 255, 255, 255],
+
+ "status_offline": [0, 0, 0, 255],
+ "status_ready": [0, 205, 0, 255],
+ "status_busy": [12, 169, 227, 255],
+ "status_paused": [255, 140, 0, 255],
+ "status_stopped": [236, 82, 80, 255]
},
"sizes": {
@@ -166,6 +177,7 @@
"sidebar": [35.0, 10.0],
"sidebar_header": [0.0, 4.0],
+ "sidebar_header_highlight": [0.5, 0.5],
"sidebar_header_mode_toggle": [0.0, 2.0],
"sidebar_lining": [0.5, 0.5],
"sidebar_setup": [0.0, 2.0],