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 @@ + + + + + + image/svg+xml + + Fill 1 Copy 3 + + + + + + Fill 1 Copy 3 + Created with Sketch. + + + + + + + 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 @@ + + + + + + image/svg+xml + + Fill 1 Copy 3 + + + + + + Fill 1 Copy 3 + Created with Sketch. + + + + + + + + + + + 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 @@ + + + + + + image/svg+xml + + Fill 1 Copy 3 + + + + + + Fill 1 Copy 3 + Created with Sketch. + + + + + + + + + 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 @@ + + + + + + image/svg+xml + + Fill 1 Copy 3 + + + + + + Fill 1 Copy 3 + Created with Sketch. + + + + + + + + + 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 @@ + + + + + + image/svg+xml + + Fill 1 Copy 3 + + + + + + Fill 1 Copy 3 + Created with Sketch. + + + + + + + + + + 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 @@ + + + + + + image/svg+xml + + Fill 1 Copy 3 + + + + + + Fill 1 Copy 3 + Created with Sketch. + + + + + + + + + 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 @@ + + + + + + image/svg+xml + + Rectangle 2365 Copy 3 + + + + + + Rectangle 2365 Copy 3 + Created with Sketch. + + + + + + + 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],