diff --git a/cura/CuraApplication.py b/cura/CuraApplication.py index eec6c7f503..c9466a0093 100755 --- a/cura/CuraApplication.py +++ b/cura/CuraApplication.py @@ -1,6 +1,5 @@ # Copyright (c) 2017 Ultimaker B.V. # Cura is released under the terms of the LGPLv3 or higher. - from PyQt5.QtNetwork import QLocalServer from PyQt5.QtNetwork import QLocalSocket diff --git a/cura/Stages/CuraStage.py b/cura/Stages/CuraStage.py index 6d4e56473d..8b7822ed7a 100644 --- a/cura/Stages/CuraStage.py +++ b/cura/Stages/CuraStage.py @@ -1,18 +1,22 @@ # Copyright (c) 2017 Ultimaker B.V. # Cura is released under the terms of the LGPLv3 or higher. -from PyQt5.QtCore import pyqtProperty, QObject +from PyQt5.QtCore import pyqtProperty, QUrl, QObject from UM.Stage import Stage class CuraStage(Stage): - def __init__(self): - super().__init__() + def __init__(self, parent = None): + super().__init__(parent) - @pyqtProperty(QObject, constant = True) + @pyqtProperty(str, constant = True) + def stageId(self): + return self.getPluginId() + + @pyqtProperty(QUrl, constant = True) def mainComponent(self): return self.getDisplayComponent("main") - @pyqtProperty(QObject, constant = True) + @pyqtProperty(QUrl, constant = True) def sidebarComponent(self): return self.getDisplayComponent("sidebar") diff --git a/plugins/MonitorStage/MonitorStage.py b/plugins/MonitorStage/MonitorStage.py index 7cd6fe5063..6131e5538b 100644 --- a/plugins/MonitorStage/MonitorStage.py +++ b/plugins/MonitorStage/MonitorStage.py @@ -9,14 +9,13 @@ from cura.Stages.CuraStage import CuraStage ## Stage for monitoring a 3D printing while it's printing. class MonitorStage(CuraStage): - def __init__(self): - super().__init__() + def __init__(self, parent = None): + super().__init__(parent) Application.getInstance().engineCreatedSignal.connect(self._engineCreated) # TODO: connect output device state to icon source def _engineCreated(self): # Note: currently the sidebar component for prepare and monitor stages is the same, this will change with the printer output device refactor! sidebar_component_path = os.path.join(Resources.getPath(Application.getInstance().ResourceTypes.QmlFiles), "Sidebar.qml") - sidebar_component = Application.getInstance().createQmlComponent(sidebar_component_path) - self.addDisplayComponent("sidebar", sidebar_component) + self.addDisplayComponent("sidebar", sidebar_component_path) self.setIconSource(Application.getInstance().getTheme().getIcon("tab_status_connected")) diff --git a/plugins/PrepareStage/PrepareStage.py b/plugins/PrepareStage/PrepareStage.py index 63086b3e93..9d4d632845 100644 --- a/plugins/PrepareStage/PrepareStage.py +++ b/plugins/PrepareStage/PrepareStage.py @@ -9,11 +9,10 @@ from cura.Stages.CuraStage import CuraStage ## Stage for preparing model (slicing). class PrepareStage(CuraStage): - def __init__(self): - super().__init__() + def __init__(self, parent = None): + super().__init__(parent) Application.getInstance().engineCreatedSignal.connect(self._engineCreated) def _engineCreated(self): sidebar_component_path = os.path.join(Resources.getPath(Application.getInstance().ResourceTypes.QmlFiles), "Sidebar.qml") - sidebar_component = Application.getInstance().createQmlComponent(sidebar_component_path) - self.addDisplayComponent("sidebar", sidebar_component) + self.addDisplayComponent("sidebar", sidebar_component_path) diff --git a/resources/qml/Cura.qml b/resources/qml/Cura.qml index 662de05063..445325df90 100644 --- a/resources/qml/Cura.qml +++ b/resources/qml/Cura.qml @@ -377,7 +377,8 @@ UM.MainWindow width: UM.Theme.getSize("sidebar").width z: 1 - sourceComponent: UM.Controller.activeStage.sidebarComponent + source: UM.Controller.activeStage.sidebarComponent + asynchronous: true } Loader @@ -390,10 +391,6 @@ UM.MainWindow bottom: parent.bottom left: parent.left right: sidebar.left -// horizontalCenter: parent.horizontalCenter -// verticalCenter: parent.verticalCenter -// horizontalCenterOffset: - UM.Theme.getSize("sidebar").width / 2 -// verticalCenterOffset: UM.Theme.getSize("sidebar_header").height / 2 } // MouseArea @@ -403,7 +400,8 @@ UM.MainWindow // onWheel: wheel.accepted = true // } - sourceComponent: UM.Controller.activeStage.mainComponent + source: UM.Controller.activeStage.mainComponent + asynchronous: true } UM.MessageStack diff --git a/resources/qml/Sidebar.qml b/resources/qml/Sidebar.qml index 992ad1f848..a02454d298 100644 --- a/resources/qml/Sidebar.qml +++ b/resources/qml/Sidebar.qml @@ -10,606 +10,601 @@ import UM 1.2 as UM import Cura 1.0 as Cura import "Menus" -Component + +Rectangle { - Rectangle + id: base; + + property int currentModeIndex; + property bool hideSettings: PrintInformation.preSliced + property bool hideView: Cura.MachineManager.activeMachineName == "" + + // Is there an output device for this printer? + property bool printerConnected: Cura.MachineManager.printerOutputDevices.length != 0 + property bool printerAcceptsCommands: printerConnected && Cura.MachineManager.printerOutputDevices[0].acceptsCommands + property var connectedPrinter: Cura.MachineManager.printerOutputDevices.length >= 1 ? Cura.MachineManager.printerOutputDevices[0] : null + property int backendState: UM.Backend.state + + property bool monitoringPrint: UM.Controller.activeStage.stageId == "MonitorStage" + + property variant printDuration: PrintInformation.currentPrintTime + property variant printMaterialLengths: PrintInformation.materialLengths + property variant printMaterialWeights: PrintInformation.materialWeights + property variant printMaterialCosts: PrintInformation.materialCosts + property variant printMaterialNames: PrintInformation.materialNames + + color: UM.Theme.getColor("sidebar") + UM.I18nCatalog { id: catalog; name:"cura"} + + Timer { + id: tooltipDelayTimer + interval: 500 + repeat: false + property var item + property string text + + onTriggered: + { + base.showTooltip(base, {x: 0, y: item.y}, text); + } + } + + function showTooltip(item, position, text) { - id: base; + tooltip.text = text; + position = item.mapToItem(base, position.x - UM.Theme.getSize("default_arrow").width, position.y); + tooltip.show(position); + } - property int currentModeIndex; - property bool hideSettings: PrintInformation.preSliced - property bool hideView: Cura.MachineManager.activeMachineName == "" + function hideTooltip() + { + tooltip.hide(); + } - // Is there an output device for this printer? - property bool printerConnected: Cura.MachineManager.printerOutputDevices.length != 0 - property bool printerAcceptsCommands: printerConnected && Cura.MachineManager.printerOutputDevices[0].acceptsCommands - property var connectedPrinter: Cura.MachineManager.printerOutputDevices.length >= 1 ? Cura.MachineManager.printerOutputDevices[0] : null - property int backendState: UM.Backend.state + function strPadLeft(string, pad, length) { + return (new Array(length + 1).join(pad) + string).slice(-length); + } - property bool monitoringPrint: UM.Controller.activeStage.id == "MonitorStage" + 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); - property variant printDuration: PrintInformation.currentPrintTime - property variant printMaterialLengths: PrintInformation.materialLengths - property variant printMaterialWeights: PrintInformation.materialWeights - property variant printMaterialCosts: PrintInformation.materialCosts - property variant printMaterialNames: PrintInformation.materialNames + var finalTime = strPadLeft(hours, "0", 2) + ':' + strPadLeft(minutes,'0',2)+ ':' + strPadLeft(seconds,'0',2); + return finalTime; + } - color: UM.Theme.getColor("sidebar") - UM.I18nCatalog { id: catalog; name:"cura"} + MouseArea + { + anchors.fill: parent + acceptedButtons: Qt.AllButtons; - Timer { - id: tooltipDelayTimer - interval: 500 - repeat: false - property var item - property string text + onWheel: + { + wheel.accepted = true; + } + } - onTriggered: + SidebarHeader { + id: header + width: parent.width + visible: machineExtruderCount.properties.value > 1 || Cura.MachineManager.hasMaterials || Cura.MachineManager.hasVariants + onShowTooltip: base.showTooltip(item, location, text) + onHideTooltip: base.hideTooltip() + } + + Rectangle { + id: headerSeparator + width: parent.width + visible: settingsModeSelection.visible && header.visible + height: visible ? UM.Theme.getSize("sidebar_lining").height : 0 + color: UM.Theme.getColor("sidebar_lining") + anchors.top: header.bottom + anchors.topMargin: visible ? UM.Theme.getSize("sidebar_margin").height : 0 + } + + Label { + id: settingsModeLabel + text: !hideSettings ? catalog.i18nc("@label:listbox", "Print Setup") : catalog.i18nc("@label:listbox","Print Setup disabled\nG-code files cannot be modified"); + anchors.left: parent.left + anchors.leftMargin: UM.Theme.getSize("sidebar_margin").width + anchors.top: headerSeparator.bottom + anchors.topMargin: UM.Theme.getSize("sidebar_margin").height + width: Math.floor(parent.width * 0.45) + font: UM.Theme.getFont("large") + color: UM.Theme.getColor("text") + visible: !monitoringPrint && !hideView + } + + Rectangle { + id: settingsModeSelection + color: "transparent" + width: Math.floor(parent.width * 0.55) + height: UM.Theme.getSize("sidebar_header_mode_toggle").height + anchors.right: parent.right + anchors.rightMargin: UM.Theme.getSize("sidebar_margin").width + anchors.top: + { + if (settingsModeLabel.contentWidth >= parent.width - width - UM.Theme.getSize("sidebar_margin").width * 2) { - base.showTooltip(base, {x: 0, y: item.y}, text); + return settingsModeLabel.bottom; + } + else + { + return headerSeparator.bottom; } } - - function showTooltip(item, position, text) - { - tooltip.text = text; - position = item.mapToItem(base, position.x - UM.Theme.getSize("default_arrow").width, position.y); - tooltip.show(position); - } - - function hideTooltip() - { - 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 - acceptedButtons: Qt.AllButtons; - - onWheel: - { - wheel.accepted = true; - } - } - - SidebarHeader { - id: header - width: parent.width - visible: machineExtruderCount.properties.value > 1 || Cura.MachineManager.hasMaterials || Cura.MachineManager.hasVariantst - onShowTooltip: base.showTooltip(item, location, text) - onHideTooltip: base.hideTooltip() - } - - Rectangle { - id: headerSeparator - width: parent.width - visible: settingsModeSelection.visible && header.visible - height: visible ? UM.Theme.getSize("sidebar_lining").height : 0 - color: UM.Theme.getColor("sidebar_lining") - anchors.top: header.bottom - anchors.topMargin: visible ? UM.Theme.getSize("sidebar_margin").height : 0 - } - - Label { - id: settingsModeLabel - text: !hideSettings ? catalog.i18nc("@label:listbox", "Print Setup") : catalog.i18nc("@label:listbox","Print Setup disabled\nG-code files cannot be modified"); - anchors.left: parent.left - anchors.leftMargin: UM.Theme.getSize("sidebar_margin").width - anchors.top: headerSeparator.bottom - anchors.topMargin: UM.Theme.getSize("sidebar_margin").height - width: Math.floor(parent.width * 0.45) - font: UM.Theme.getFont("large") - color: UM.Theme.getColor("text") - visible: !monitoringPrint && !hideView - } - - Rectangle { - id: settingsModeSelection - color: "transparent" - width: Math.floor(parent.width * 0.55) - height: UM.Theme.getSize("sidebar_header_mode_toggle").height - anchors.right: parent.right - anchors.rightMargin: UM.Theme.getSize("sidebar_margin").width - anchors.top: - { - if (settingsModeLabel.contentWidth >= parent.width - width - UM.Theme.getSize("sidebar_margin").width * 2) - { - return settingsModeLabel.bottom; - } - else - { - return headerSeparator.bottom; - } - } - anchors.topMargin: UM.Theme.getSize("sidebar_margin").height - visible: !monitoringPrint && !hideSettings && !hideView - Component{ - id: wizardDelegate - Button { - height: settingsModeSelection.height - anchors.left: parent.left - anchors.leftMargin: model.index * Math.floor(settingsModeSelection.width / 2) - anchors.verticalCenter: parent.verticalCenter - width: Math.floor(0.5 * parent.width) - text: model.text - exclusiveGroup: modeMenuGroup; - checkable: true; - checked: base.currentModeIndex == index - onClicked: base.currentModeIndex = index - - onHoveredChanged: { - if (hovered) - { - tooltipDelayTimer.item = settingsModeSelection - tooltipDelayTimer.text = model.tooltipText - tooltipDelayTimer.start(); - } - else - { - tooltipDelayTimer.stop(); - base.hideTooltip(); - } - } - - style: ButtonStyle { - background: Rectangle { - border.width: control.checked ? UM.Theme.getSize("default_lining").width * 2 : UM.Theme.getSize("default_lining").width - border.color: (control.checked || 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.checked || 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; } } - Label { - anchors.left: parent.left - anchors.right: parent.right - anchors.verticalCenter: parent.verticalCenter - anchors.leftMargin: UM.Theme.getSize("default_lining").width * 2 - anchors.rightMargin: UM.Theme.getSize("default_lining").width * 2 - color: (control.checked || 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("default") - text: control.text - horizontalAlignment: Text.AlignHCenter - elide: Text.ElideMiddle - } - } - label: Item { } - } - } - } - ExclusiveGroup { id: modeMenuGroup; } - - ListView - { - id: modesList - property var index: 0 - model: modesListModel - delegate: wizardDelegate - anchors.top: parent.top + anchors.topMargin: UM.Theme.getSize("sidebar_margin").height + visible: !monitoringPrint && !hideSettings && !hideView + Component{ + id: wizardDelegate + Button { + height: settingsModeSelection.height anchors.left: parent.left - width: parent.width - } - } + anchors.leftMargin: model.index * Math.floor(settingsModeSelection.width / 2) + anchors.verticalCenter: parent.verticalCenter + width: Math.floor(0.5 * parent.width) + text: model.text + exclusiveGroup: modeMenuGroup; + checkable: true; + checked: base.currentModeIndex == index + onClicked: base.currentModeIndex = index - StackView - { - id: sidebarContents - - anchors.bottom: footerSeparator.top - anchors.top: settingsModeSelection.bottom - anchors.topMargin: UM.Theme.getSize("sidebar_margin").height - anchors.left: base.left - anchors.right: base.right - visible: !monitoringPrint && !hideSettings - - delegate: StackViewDelegate - { - function transitionFinished(properties) - { - properties.exitItem.opacity = 1 - } - - pushTransition: StackViewTransition - { - PropertyAnimation + onHoveredChanged: { + if (hovered) { - target: enterItem - property: "opacity" - from: 0 - to: 1 - duration: 100 - } - PropertyAnimation - { - target: exitItem - property: "opacity" - from: 1 - to: 0 - duration: 100 - } - } - } - } - - Loader - { - id: controlItem - anchors.bottom: footerSeparator.top - anchors.top: headerSeparator.bottom - anchors.left: base.left - anchors.right: base.right - sourceComponent: - { - if(monitoringPrint && connectedPrinter != null) - { - if(connectedPrinter.controlItem != null) - { - return connectedPrinter.controlItem - } - } - return null - } - } - - Loader - { - anchors.bottom: footerSeparator.top - anchors.top: headerSeparator.bottom - anchors.left: base.left - anchors.right: base.right - source: - { - if(controlItem.sourceComponent == null) - { - if(monitoringPrint) - { - return "PrintMonitor.qml" - } else - { - return "SidebarContents.qml" - } - } - else - { - return "" - } - } - } - - Rectangle - { - id: footerSeparator - width: parent.width - height: UM.Theme.getSize("sidebar_lining").height - color: UM.Theme.getColor("sidebar_lining") - anchors.bottom: printSpecs.top - anchors.bottomMargin: Math.floor(UM.Theme.getSize("sidebar_margin").height * 2 + UM.Theme.getSize("progressbar").height + UM.Theme.getFont("default_bold").pixelSize) - } - - Item - { - id: printSpecs - anchors.left: parent.left - anchors.bottom: parent.bottom - anchors.leftMargin: UM.Theme.getSize("sidebar_margin").width - anchors.bottomMargin: UM.Theme.getSize("sidebar_margin").height - height: timeDetails.height + costSpec.height - width: base.width - (saveButton.buttonRowWidth + UM.Theme.getSize("sidebar_margin").width) - visible: !monitoringPrint - clip: true - - Label - { - id: timeDetails - anchors.left: parent.left - anchors.bottom: costSpec.top - font: UM.Theme.getFont("large") - color: UM.Theme.getColor("text_subtext") - text: (!base.printDuration || !base.printDuration.valid) ? catalog.i18nc("@label Hours and minutes", "00h 00min") : base.printDuration.getDisplayString(UM.DurationFormat.Short) - - MouseArea - { - id: timeDetailsMouseArea - anchors.fill: parent - hoverEnabled: true - - onEntered: - { - if(base.printDuration.valid && !base.printDuration.isTotalDurationZero) - { - // All the time information for the different features is achieved - var print_time = PrintInformation.getFeaturePrintTimes(); - var total_seconds = parseInt(base.printDuration.getDisplayString(UM.DurationFormat.Seconds)) - - // A message is created and displayed when the user hover the time label - var tooltip_html = "%1
".arg(catalog.i18nc("@tooltip", "Time specification")); - for(var feature in print_time) - { - if(!print_time[feature].isTotalDurationZero) - { - tooltip_html += "" + - "".arg(print_time[feature].getDisplayString(UM.DurationFormat.ISO8601).slice(0,-3)) + - "".arg(Math.round(100 * parseInt(print_time[feature].getDisplayString(UM.DurationFormat.Seconds)) / total_seconds)) + - ""; - } - } - tooltip_html += "
" + feature + ":  %1  %1%
"; - - base.showTooltip(parent, Qt.point(-UM.Theme.getSize("sidebar_margin").width, 0), tooltip_html); - } - } - onExited: - { - base.hideTooltip(); - } - } - } - - Label - { - function formatRow(items) - { - var row_html = ""; - for(var item = 0; item < items.length; item++) - { - if (item == 0) - { - row_html += "%1".arg(items[item]); - } - else - { - row_html += "  %1".arg(items[item]); - } - } - row_html += ""; - return row_html; - } - - function getSpecsData() - { - var lengths = []; - var total_length = 0; - var weights = []; - var total_weight = 0; - var costs = []; - var total_cost = 0; - var some_costs_known = false; - var names = []; - if(base.printMaterialLengths) - { - for(var index = 0; index < base.printMaterialLengths.length; index++) - { - if(base.printMaterialLengths[index] > 0) - { - names.push(base.printMaterialNames[index]); - lengths.push(base.printMaterialLengths[index].toFixed(2)); - weights.push(String(Math.floor(base.printMaterialWeights[index]))); - var cost = base.printMaterialCosts[index] == undefined ? 0 : base.printMaterialCosts[index].toFixed(2); - costs.push(cost); - if(cost > 0) - { - some_costs_known = true; - } - - total_length += base.printMaterialLengths[index]; - total_weight += base.printMaterialWeights[index]; - total_cost += base.printMaterialCosts[index]; - } - } - } - if(lengths.length == 0) - { - lengths = ["0.00"]; - weights = ["0"]; - costs = ["0.00"]; - } - - var tooltip_html = "%1
".arg(catalog.i18nc("@label", "Cost specification")); - for(var index = 0; index < lengths.length; index++) - { - tooltip_html += formatRow([ - "%1:".arg(names[index]), - catalog.i18nc("@label m for meter", "%1m").arg(lengths[index]), - catalog.i18nc("@label g for grams", "%1g").arg(weights[index]), - "%1 %2".arg(UM.Preferences.getValue("cura/currency")).arg(costs[index]), - ]); - } - if(lengths.length > 1) - { - tooltip_html += formatRow([ - catalog.i18nc("@label", "Total:"), - catalog.i18nc("@label m for meter", "%1m").arg(total_length.toFixed(2)), - catalog.i18nc("@label g for grams", "%1g").arg(Math.round(total_weight)), - "%1 %2".arg(UM.Preferences.getValue("cura/currency")).arg(total_cost.toFixed(2)), - ]); - } - tooltip_html += "
"; - tooltipText = tooltip_html; - - return tooltipText - } - - id: costSpec - anchors.left: parent.left - anchors.bottom: parent.bottom - font: UM.Theme.getFont("very_small") - color: UM.Theme.getColor("text_subtext") - elide: Text.ElideMiddle - width: parent.width - property string tooltipText - text: - { - var lengths = []; - var weights = []; - var costs = []; - var someCostsKnown = false; - if(base.printMaterialLengths) { - for(var index = 0; index < base.printMaterialLengths.length; index++) - { - if(base.printMaterialLengths[index] > 0) - { - lengths.push(base.printMaterialLengths[index].toFixed(2)); - weights.push(String(Math.floor(base.printMaterialWeights[index]))); - var cost = base.printMaterialCosts[index] == undefined ? 0 : base.printMaterialCosts[index].toFixed(2); - costs.push(cost); - if(cost > 0) - { - someCostsKnown = true; - } - } - } - } - if(lengths.length == 0) - { - lengths = ["0.00"]; - weights = ["0"]; - costs = ["0.00"]; - } - if(someCostsKnown) - { - return catalog.i18nc("@label Print estimates: m for meters, g for grams, %4 is currency and %3 is print cost", "%1m / ~ %2g / ~ %4 %3").arg(lengths.join(" + ")) - .arg(weights.join(" + ")).arg(costs.join(" + ")).arg(UM.Preferences.getValue("cura/currency")); + tooltipDelayTimer.item = settingsModeSelection + tooltipDelayTimer.text = model.tooltipText + tooltipDelayTimer.start(); } else { - return catalog.i18nc("@label Print estimates: m for meters, g for grams", "%1m / ~ %2g").arg(lengths.join(" + ")).arg(weights.join(" + ")); - } - } - MouseArea - { - id: costSpecMouseArea - anchors.fill: parent - hoverEnabled: true - - onEntered: - { - - if(base.printDuration.valid && !base.printDuration.isTotalDurationZero) - { - var show_data = costSpec.getSpecsData() - - base.showTooltip(parent, Qt.point(-UM.Theme.getSize("sidebar_margin").width, 0), show_data); - } - } - onExited: - { + tooltipDelayTimer.stop(); base.hideTooltip(); } } + + style: ButtonStyle { + background: Rectangle { + border.width: control.checked ? UM.Theme.getSize("default_lining").width * 2 : UM.Theme.getSize("default_lining").width + border.color: (control.checked || 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.checked || 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; } } + Label { + anchors.left: parent.left + anchors.right: parent.right + anchors.verticalCenter: parent.verticalCenter + anchors.leftMargin: UM.Theme.getSize("default_lining").width * 2 + anchors.rightMargin: UM.Theme.getSize("default_lining").width * 2 + color: (control.checked || 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("default") + text: control.text + horizontalAlignment: Text.AlignHCenter + elide: Text.ElideMiddle + } + } + label: Item { } + } } } + ExclusiveGroup { id: modeMenuGroup; } - // SaveButton and MonitorButton are actually the bottom footer panels. - // "!monitoringPrint" currently means "show-settings-mode" - SaveButton + ListView { - id: saveButton - implicitWidth: base.width - anchors.top: footerSeparator.bottom - anchors.topMargin: UM.Theme.getSize("sidebar_margin").height - anchors.bottom: parent.bottom - visible: !monitoringPrint - } - - MonitorButton - { - id: monitorButton - implicitWidth: base.width - anchors.top: footerSeparator.bottom - anchors.topMargin: UM.Theme.getSize("sidebar_margin").height - anchors.bottom: parent.bottom - visible: monitoringPrint - } - - - SidebarTooltip - { - id: tooltip; - } - - // Setting mode: Recommended or Custom - ListModel - { - id: modesListModel; - } - - SidebarSimple - { - id: sidebarSimple; - visible: false; - - onShowTooltip: base.showTooltip(item, location, text) - onHideTooltip: base.hideTooltip() - } - - SidebarAdvanced - { - id: sidebarAdvanced; - visible: false; - - onShowTooltip: base.showTooltip(item, location, text) - onHideTooltip: base.hideTooltip() - } - - Component.onCompleted: - { - modesListModel.append({ - text: catalog.i18nc("@title:tab", "Recommended"), - tooltipText: catalog.i18nc("@tooltip", "Recommended Print Setup

Print with the recommended settings for the selected printer, material and quality."), - item: sidebarSimple - }) - modesListModel.append({ - text: catalog.i18nc("@title:tab", "Custom"), - tooltipText: catalog.i18nc("@tooltip", "Custom Print Setup

Print with finegrained control over every last bit of the slicing process."), - item: sidebarAdvanced - }) - sidebarContents.push({ "item": modesListModel.get(base.currentModeIndex).item, "immediate": true }); - - var index = Math.floor(UM.Preferences.getValue("cura/active_mode")) - if(index) - { - currentModeIndex = index; - } - } - - 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 + id: modesList + property var index: 0 + model: modesListModel + delegate: wizardDelegate + anchors.top: parent.top + anchors.left: parent.left + width: parent.width } } + + StackView + { + id: sidebarContents + + anchors.bottom: footerSeparator.top + anchors.top: settingsModeSelection.bottom + anchors.topMargin: UM.Theme.getSize("sidebar_margin").height + anchors.left: base.left + anchors.right: base.right + visible: !monitoringPrint && !hideSettings + + delegate: StackViewDelegate + { + function transitionFinished(properties) + { + properties.exitItem.opacity = 1 + } + + pushTransition: StackViewTransition + { + PropertyAnimation + { + target: enterItem + property: "opacity" + from: 0 + to: 1 + duration: 100 + } + PropertyAnimation + { + target: exitItem + property: "opacity" + from: 1 + to: 0 + duration: 100 + } + } + } + } + + Loader + { + id: controlItem + anchors.bottom: footerSeparator.top + anchors.top: headerSeparator.bottom + anchors.left: base.left + anchors.right: base.right + sourceComponent: + { + if(monitoringPrint && connectedPrinter != null) + { + if(connectedPrinter.controlItem != null) + { + return connectedPrinter.controlItem + } + } + return null + } + } + + Loader + { + anchors.bottom: footerSeparator.top + anchors.top: headerSeparator.bottom + anchors.left: base.left + anchors.right: base.right + source: + { + if(controlItem.sourceComponent == null) + { + if(monitoringPrint) + { + return "PrintMonitor.qml" + } else + { + return "SidebarContents.qml" + } + } + else + { + return "" + } + } + } + + Rectangle + { + id: footerSeparator + width: parent.width + height: UM.Theme.getSize("sidebar_lining").height + color: UM.Theme.getColor("sidebar_lining") + anchors.bottom: printSpecs.top + anchors.bottomMargin: Math.floor(UM.Theme.getSize("sidebar_margin").height * 2 + UM.Theme.getSize("progressbar").height + UM.Theme.getFont("default_bold").pixelSize) + } + + Item + { + id: printSpecs + anchors.left: parent.left + anchors.bottom: parent.bottom + anchors.leftMargin: UM.Theme.getSize("sidebar_margin").width + anchors.bottomMargin: UM.Theme.getSize("sidebar_margin").height + height: timeDetails.height + costSpec.height + width: base.width - (saveButton.buttonRowWidth + UM.Theme.getSize("sidebar_margin").width) + visible: !monitoringPrint + clip: true + + Label + { + id: timeDetails + anchors.left: parent.left + anchors.bottom: costSpec.top + font: UM.Theme.getFont("large") + color: UM.Theme.getColor("text_subtext") + text: (!base.printDuration || !base.printDuration.valid) ? catalog.i18nc("@label Hours and minutes", "00h 00min") : base.printDuration.getDisplayString(UM.DurationFormat.Short) + + MouseArea + { + id: timeDetailsMouseArea + anchors.fill: parent + hoverEnabled: true + + onEntered: + { + if(base.printDuration.valid && !base.printDuration.isTotalDurationZero) + { + // All the time information for the different features is achieved + var print_time = PrintInformation.getFeaturePrintTimes(); + var total_seconds = parseInt(base.printDuration.getDisplayString(UM.DurationFormat.Seconds)) + + // A message is created and displayed when the user hover the time label + var tooltip_html = "%1
".arg(catalog.i18nc("@tooltip", "Time specification")); + for(var feature in print_time) + { + if(!print_time[feature].isTotalDurationZero) + { + tooltip_html += "" + + "".arg(print_time[feature].getDisplayString(UM.DurationFormat.ISO8601).slice(0,-3)) + + "".arg(Math.round(100 * parseInt(print_time[feature].getDisplayString(UM.DurationFormat.Seconds)) / total_seconds)) + + ""; + } + } + tooltip_html += "
" + feature + ":  %1  %1%
"; + + base.showTooltip(parent, Qt.point(-UM.Theme.getSize("sidebar_margin").width, 0), tooltip_html); + } + } + onExited: + { + base.hideTooltip(); + } + } + } + + Label + { + function formatRow(items) + { + var row_html = ""; + for(var item = 0; item < items.length; item++) + { + if (item == 0) + { + row_html += "%1".arg(items[item]); + } + else + { + row_html += "  %1".arg(items[item]); + } + } + row_html += ""; + return row_html; + } + + function getSpecsData() + { + var lengths = []; + var total_length = 0; + var weights = []; + var total_weight = 0; + var costs = []; + var total_cost = 0; + var some_costs_known = false; + var names = []; + if(base.printMaterialLengths) + { + for(var index = 0; index < base.printMaterialLengths.length; index++) + { + if(base.printMaterialLengths[index] > 0) + { + names.push(base.printMaterialNames[index]); + lengths.push(base.printMaterialLengths[index].toFixed(2)); + weights.push(String(Math.floor(base.printMaterialWeights[index]))); + var cost = base.printMaterialCosts[index] == undefined ? 0 : base.printMaterialCosts[index].toFixed(2); + costs.push(cost); + if(cost > 0) + { + some_costs_known = true; + } + + total_length += base.printMaterialLengths[index]; + total_weight += base.printMaterialWeights[index]; + total_cost += base.printMaterialCosts[index]; + } + } + } + if(lengths.length == 0) + { + lengths = ["0.00"]; + weights = ["0"]; + costs = ["0.00"]; + } + + var tooltip_html = "%1
".arg(catalog.i18nc("@label", "Cost specification")); + for(var index = 0; index < lengths.length; index++) + { + tooltip_html += formatRow([ + "%1:".arg(names[index]), + catalog.i18nc("@label m for meter", "%1m").arg(lengths[index]), + catalog.i18nc("@label g for grams", "%1g").arg(weights[index]), + "%1 %2".arg(UM.Preferences.getValue("cura/currency")).arg(costs[index]), + ]); + } + if(lengths.length > 1) + { + tooltip_html += formatRow([ + catalog.i18nc("@label", "Total:"), + catalog.i18nc("@label m for meter", "%1m").arg(total_length.toFixed(2)), + catalog.i18nc("@label g for grams", "%1g").arg(Math.round(total_weight)), + "%1 %2".arg(UM.Preferences.getValue("cura/currency")).arg(total_cost.toFixed(2)), + ]); + } + tooltip_html += "
"; + tooltipText = tooltip_html; + + return tooltipText + } + + id: costSpec + anchors.left: parent.left + anchors.bottom: parent.bottom + font: UM.Theme.getFont("very_small") + color: UM.Theme.getColor("text_subtext") + elide: Text.ElideMiddle + width: parent.width + property string tooltipText + text: + { + var lengths = []; + var weights = []; + var costs = []; + var someCostsKnown = false; + if(base.printMaterialLengths) { + for(var index = 0; index < base.printMaterialLengths.length; index++) + { + if(base.printMaterialLengths[index] > 0) + { + lengths.push(base.printMaterialLengths[index].toFixed(2)); + weights.push(String(Math.floor(base.printMaterialWeights[index]))); + var cost = base.printMaterialCosts[index] == undefined ? 0 : base.printMaterialCosts[index].toFixed(2); + costs.push(cost); + if(cost > 0) + { + someCostsKnown = true; + } + } + } + } + if(lengths.length == 0) + { + lengths = ["0.00"]; + weights = ["0"]; + costs = ["0.00"]; + } + if(someCostsKnown) + { + return catalog.i18nc("@label Print estimates: m for meters, g for grams, %4 is currency and %3 is print cost", "%1m / ~ %2g / ~ %4 %3").arg(lengths.join(" + ")) + .arg(weights.join(" + ")).arg(costs.join(" + ")).arg(UM.Preferences.getValue("cura/currency")); + } + else + { + return catalog.i18nc("@label Print estimates: m for meters, g for grams", "%1m / ~ %2g").arg(lengths.join(" + ")).arg(weights.join(" + ")); + } + } + MouseArea + { + id: costSpecMouseArea + anchors.fill: parent + hoverEnabled: true + + onEntered: + { + + if(base.printDuration.valid && !base.printDuration.isTotalDurationZero) + { + var show_data = costSpec.getSpecsData() + + base.showTooltip(parent, Qt.point(-UM.Theme.getSize("sidebar_margin").width, 0), show_data); + } + } + onExited: + { + base.hideTooltip(); + } + } + } + } + + // SaveButton and MonitorButton are actually the bottom footer panels. + // "!monitoringPrint" currently means "show-settings-mode" + SaveButton + { + id: saveButton + implicitWidth: base.width + anchors.top: footerSeparator.bottom + anchors.topMargin: UM.Theme.getSize("sidebar_margin").height + anchors.bottom: parent.bottom + visible: !monitoringPrint + } + + MonitorButton + { + id: monitorButton + implicitWidth: base.width + anchors.top: footerSeparator.bottom + anchors.topMargin: UM.Theme.getSize("sidebar_margin").height + anchors.bottom: parent.bottom + visible: monitoringPrint + } + + SidebarTooltip + { + id: tooltip; + } + + // Setting mode: Recommended or Custom + ListModel + { + id: modesListModel; + } + + SidebarSimple + { + id: sidebarSimple; + visible: false; + + onShowTooltip: base.showTooltip(item, location, text) + onHideTooltip: base.hideTooltip() + } + + SidebarAdvanced + { + id: sidebarAdvanced; + visible: false; + + onShowTooltip: base.showTooltip(item, location, text) + onHideTooltip: base.hideTooltip() + } + + Component.onCompleted: + { + modesListModel.append({ + text: catalog.i18nc("@title:tab", "Recommended"), + tooltipText: catalog.i18nc("@tooltip", "Recommended Print Setup

Print with the recommended settings for the selected printer, material and quality."), + item: sidebarSimple + }) + modesListModel.append({ + text: catalog.i18nc("@title:tab", "Custom"), + tooltipText: catalog.i18nc("@tooltip", "Custom Print Setup

Print with finegrained control over every last bit of the slicing process."), + item: sidebarAdvanced + }) + sidebarContents.push({ "item": modesListModel.get(base.currentModeIndex).item, "immediate": true }); + + var index = Math.floor(UM.Preferences.getValue("cura/active_mode")) + if(index) + { + currentModeIndex = index; + } + } + + 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 + } } diff --git a/resources/qml/SidebarSimple.qml b/resources/qml/SidebarSimple.qml index e923963355..4b182c7a72 100644 --- a/resources/qml/SidebarSimple.qml +++ b/resources/qml/SidebarSimple.qml @@ -403,8 +403,6 @@ Item } } - - // // Infill // @@ -568,18 +566,24 @@ Item model: infillModel anchors.fill: parent - property int activeIndex: { + function activeIndex () { for (var i = 0; i < infillModel.count; i++) { var density = parseInt(infillDensity.properties.value) var steps = parseInt(infillSteps.properties.value) var infillModelItem = infillModel.get(i) - if (density >= infillModelItem.percentageMin + // TODO: somehow this print causes this method not to crash QML when the sidebar view gets unloaded (when switching states) + // TODO: That should be fixed :P + print("test", density, steps, infillModelItem) + + if (infillModelItem + && density >= infillModelItem.percentageMin && density <= infillModelItem.percentageMax && steps >= infillModelItem.stepsMin - && steps <= infillModelItem.stepsMax){ - return i - } + && steps <= infillModelItem.stepsMax + ){ + return i + } } return -1 } @@ -587,7 +591,7 @@ Item Rectangle { anchors.fill: parent - visible: infillIconList.activeIndex == index + visible: infillIconList.activeIndex() == index border.width: UM.Theme.getSize("default_lining").width border.color: UM.Theme.getColor("quality_slider_unavailable")