From 80b589344f22e035cbe9826fcd9ac182b696207d Mon Sep 17 00:00:00 2001 From: ChrisTerBeke Date: Thu, 25 Jan 2018 22:40:30 +0100 Subject: [PATCH 1/6] Add custom command methods to output device and controller --- cura/PrinterOutput/PrinterOutputController.py | 9 ++++++--- cura/PrinterOutput/PrinterOutputModel.py | 4 ++++ plugins/USBPrinting/USBPrinterOutputController.py | 5 ++++- 3 files changed, 14 insertions(+), 4 deletions(-) diff --git a/cura/PrinterOutput/PrinterOutputController.py b/cura/PrinterOutput/PrinterOutputController.py index 86ca10e2d3..02ab84cca8 100644 --- a/cura/PrinterOutput/PrinterOutputController.py +++ b/cura/PrinterOutput/PrinterOutputController.py @@ -39,8 +39,11 @@ class PrinterOutputController: def moveHead(self, printer: "PrinterOutputModel", x, y, z, speed): Logger.log("w", "Move head not implemented in controller") - def homeBed(self, printer): + def homeBed(self, printer: "PrinterOutputModel"): Logger.log("w", "Home bed not implemented in controller") - def homeHead(self, printer): - Logger.log("w", "Home head not implemented in controller") \ No newline at end of file + def homeHead(self, printer: "PrinterOutputModel"): + Logger.log("w", "Home head not implemented in controller") + + def sendCustomCommand(self, printer: "PrinterOutputModel", command: str): + Logger.log("w", "Custom command not implemented in controller") diff --git a/cura/PrinterOutput/PrinterOutputModel.py b/cura/PrinterOutput/PrinterOutputModel.py index 8234989519..02c1f9e489 100644 --- a/cura/PrinterOutput/PrinterOutputModel.py +++ b/cura/PrinterOutput/PrinterOutputModel.py @@ -90,6 +90,10 @@ class PrinterOutputModel(QObject): def homeBed(self): self._controller.homeBed(self) + @pyqtSlot(str) + def sendCustomCommand(self, command): + self._controller.sendCustomCommand(self, command) + @pyqtProperty("QVariantList", constant = True) def extruders(self): return self._extruders diff --git a/plugins/USBPrinting/USBPrinterOutputController.py b/plugins/USBPrinting/USBPrinterOutputController.py index f189ed5876..66941acd9e 100644 --- a/plugins/USBPrinting/USBPrinterOutputController.py +++ b/plugins/USBPrinting/USBPrinterOutputController.py @@ -31,6 +31,9 @@ class USBPrinterOutputController(PrinterOutputController): def homeBed(self, printer): self._output_device.sendCommand("G28 Z") + def sendCustomCommand(self, printer, command): + self._output_device.sendCommand(str(command)) + def setJobState(self, job: "PrintJobOutputModel", state: str): if state == "pause": self._output_device.pausePrint() @@ -65,4 +68,4 @@ class USBPrinterOutputController(PrinterOutputController): def _onPreheatBedTimerFinished(self): self.setTargetBedTemperature(self._preheat_printer, 0) - self._preheat_printer.updateIsPreheating(False) \ No newline at end of file + self._preheat_printer.updateIsPreheating(False) From 01b8bd60bdf7ef8230dd891a94738bcc0638e290 Mon Sep 17 00:00:00 2001 From: ChrisTerBeke Date: Thu, 25 Jan 2018 22:47:02 +0100 Subject: [PATCH 2/6] Add type hinting --- cura/PrinterOutput/PrinterOutputModel.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cura/PrinterOutput/PrinterOutputModel.py b/cura/PrinterOutput/PrinterOutputModel.py index 02c1f9e489..95e0daf34f 100644 --- a/cura/PrinterOutput/PrinterOutputModel.py +++ b/cura/PrinterOutput/PrinterOutputModel.py @@ -91,7 +91,7 @@ class PrinterOutputModel(QObject): self._controller.homeBed(self) @pyqtSlot(str) - def sendCustomCommand(self, command): + def sendCustomCommand(self, command: str): self._controller.sendCustomCommand(self, command) @pyqtProperty("QVariantList", constant = True) From d7254ff8d0cbf7a3fce51fe4d5fcba15e282f413 Mon Sep 17 00:00:00 2001 From: ChrisTerBeke Date: Thu, 25 Jan 2018 22:56:46 +0100 Subject: [PATCH 3/6] Start UI elements for custom command input --- .../PrinterOutput/ManualPrinterControl.qml | 23 +++++++++++++++++++ 1 file changed, 23 insertions(+) diff --git a/resources/qml/PrinterOutput/ManualPrinterControl.qml b/resources/qml/PrinterOutput/ManualPrinterControl.qml index 43fa769fb5..d3ae280d61 100644 --- a/resources/qml/PrinterOutput/ManualPrinterControl.qml +++ b/resources/qml/PrinterOutput/ManualPrinterControl.qml @@ -429,6 +429,29 @@ Item } } + Row + { + id: customCommandInputRow + + width: base.width - 2 * UM.Theme.getSize("default_margin").width + height: childrenRect.height + UM.Theme.getSize("default_margin").width + anchors.left: parent.left + anchors.leftMargin: UM.Theme.getSize("default_margin").width + + spacing: UM.Theme.getSize("default_margin").width + + Label + { + text: catalog.i18nc("@label", "Custom command input") + color: UM.Theme.getColor("setting_control_text") + font: UM.Theme.getFont("default") + + width: Math.floor(parent.width * 0.4) - UM.Theme.getSize("default_margin").width + height: UM.Theme.getSize("setting_control").height + verticalAlignment: Text.AlignVCenter + } + } + ListModel { id: distancesModel From 866e99bcbb76b3ac371b005a7b8636e6592c15c8 Mon Sep 17 00:00:00 2001 From: ChrisTerBeke Date: Thu, 25 Jan 2018 23:02:46 +0100 Subject: [PATCH 4/6] More QML for sending custom commands, not styled or tested yet --- .../PrinterOutput/ManualPrinterControl.qml | 37 +++++++++++++++++++ 1 file changed, 37 insertions(+) diff --git a/resources/qml/PrinterOutput/ManualPrinterControl.qml b/resources/qml/PrinterOutput/ManualPrinterControl.qml index d3ae280d61..0720cd1976 100644 --- a/resources/qml/PrinterOutput/ManualPrinterControl.qml +++ b/resources/qml/PrinterOutput/ManualPrinterControl.qml @@ -450,6 +450,43 @@ Item height: UM.Theme.getSize("setting_control").height verticalAlignment: Text.AlignVCenter } + + Row + { + TextInput + { + id: customCommandInput + + font: UM.Theme.getFont("default") + color: !enabled ? UM.Theme.getColor("setting_control_disabled_text") : UM.Theme.getColor("setting_control_text") + selectByMouse: true + + anchors.left: parent.left + anchors.leftMargin: UM.Theme.getSize("setting_unit_margin").width + anchors.right: parent.right + anchors.verticalCenter: parent.verticalCenter + + renderType: Text.NativeRendering + } + } + + Row + { + Button + { + id: sendCustomCommandButton + + height: UM.Theme.getSize("setting_control").height + + anchors.right: parent.right + anchors.bottom: parent.bottom + anchors.margins: UM.Theme.getSize("default_margin").width + + onClicked: { + printerModel.sendCustomCommand(customCommandInput.text) + } + } + } } ListModel From bd46515382834d8491c28022899801a3939e70c2 Mon Sep 17 00:00:00 2001 From: ChrisTerBeke Date: Fri, 26 Jan 2018 22:10:44 +0100 Subject: [PATCH 5/6] Make custom commands functional, fix UI layout, typos --- cura/PrinterOutput/PrinterOutputController.py | 4 +- resources/qml/PrinterOutput/HeatedBedBox.qml | 6 +- .../PrinterOutput/ManualPrinterControl.qml | 151 ++++++++++++------ 3 files changed, 109 insertions(+), 52 deletions(-) diff --git a/cura/PrinterOutput/PrinterOutputController.py b/cura/PrinterOutput/PrinterOutputController.py index 02ab84cca8..204bdd5b62 100644 --- a/cura/PrinterOutput/PrinterOutputController.py +++ b/cura/PrinterOutput/PrinterOutputController.py @@ -6,7 +6,7 @@ from UM.Logger import Logger MYPY = False if MYPY: from cura.PrinterOutput.PrintJobOutputModel import PrintJobOutputModel - from cura.PrinterOutput.ExtruderOuputModel import ExtruderOuputModel + from cura.PrinterOutput.ExtruderOuputModel import ExtruderOutputModel from cura.PrinterOutput.PrinterOutputModel import PrinterOutputModel @@ -18,7 +18,7 @@ class PrinterOutputController: self.can_control_manually = True self._output_device = output_device - def setTargetHotendTemperature(self, printer: "PrinterOutputModel", extruder: "ExtruderOuputModel", temperature: int): + def setTargetHotendTemperature(self, printer: "PrinterOutputModel", extruder: "ExtruderOutputModel", temperature: int): Logger.log("w", "Set target hotend temperature not implemented in controller") def setTargetBedTemperature(self, printer: "PrinterOutputModel", temperature: int): diff --git a/resources/qml/PrinterOutput/HeatedBedBox.qml b/resources/qml/PrinterOutput/HeatedBedBox.qml index bc89da2251..552f33f620 100644 --- a/resources/qml/PrinterOutput/HeatedBedBox.qml +++ b/resources/qml/PrinterOutput/HeatedBedBox.qml @@ -1,3 +1,6 @@ +// Copyright (c) 2017 Ultimaker B.V. +// Cura is released under the terms of the LGPLv3 or higher. + import QtQuick 2.2 import QtQuick.Controls 1.1 import QtQuick.Controls.Styles 1.1 @@ -11,6 +14,7 @@ Item implicitWidth: parent.width height: visible ? UM.Theme.getSize("sidebar_extruder_box").height : 0 property var printerModel + Rectangle { color: UM.Theme.getColor("sidebar") @@ -195,7 +199,7 @@ Item } } - Button //The pre-heat button. + Button // The pre-heat button. { id: preheatButton height: UM.Theme.getSize("setting_control").height diff --git a/resources/qml/PrinterOutput/ManualPrinterControl.qml b/resources/qml/PrinterOutput/ManualPrinterControl.qml index 0720cd1976..632a3de72f 100644 --- a/resources/qml/PrinterOutput/ManualPrinterControl.qml +++ b/resources/qml/PrinterOutput/ManualPrinterControl.qml @@ -9,7 +9,6 @@ import QtQuick.Layouts 1.1 import UM 1.2 as UM import Cura 1.0 as Cura - Item { property var printerModel @@ -101,29 +100,29 @@ Item Column { - enabled: - { - if (printerModel == null) - { - return false; //Can't control the printer if not connected - } - - if (!connectedDevice.acceptsCommands) - { - return false; //Not allowed to do anything. - } - - if(activePrintJob == null) - { - return true - } - - if (activePrintJob.state == "printing" || activePrintJob.state == "resuming" || activePrintJob.state == "pausing" || activePrintJob.state == "error" || activePrintJob.state == "offline") - { - return false; //Printer is in a state where it can't react to manual control - } - return true; - } +// enabled: +// { +// if (printerModel == null) +// { +// return false; //Can't control the printer if not connected +// } +// +// if (!connectedDevice.acceptsCommands) +// { +// return false; //Not allowed to do anything. +// } +// +// if(activePrintJob == null) +// { +// return true +// } +// +// if (activePrintJob.state == "printing" || activePrintJob.state == "resuming" || activePrintJob.state == "pausing" || activePrintJob.state == "error" || activePrintJob.state == "offline") +// { +// return false; //Printer is in a state where it can't react to manual control +// } +// return true; +// } MonitorSection @@ -442,7 +441,7 @@ Item Label { - text: catalog.i18nc("@label", "Custom command input") + text: catalog.i18nc("@label", "Send G-code") color: UM.Theme.getColor("setting_control_text") font: UM.Theme.getFont("default") @@ -453,37 +452,91 @@ Item Row { - TextInput + // Input field for custom G-code commands. + Rectangle { - id: customCommandInput + id: customCommandControl - font: UM.Theme.getFont("default") - color: !enabled ? UM.Theme.getColor("setting_control_disabled_text") : UM.Theme.getColor("setting_control_text") - selectByMouse: true + // state + visible: printerModel != null ? printerModel.canPreHeatBed: true + enabled: { + if (printerModel == null) { + return false // Can't preheat if not connected + } + if (!connectedPrinter.acceptsCommands) { + return false // Not allowed to do anything + } + if (connectedPrinter.jobState == "printing" || connectedPrinter.jobState == "pre_print" || connectedPrinter.jobState == "resuming" || connectedPrinter.jobState == "pausing" || connectedPrinter.jobState == "paused" || connectedPrinter.jobState == "error" || connectedPrinter.jobState == "offline") { + return false // Printer is in a state where it can't react to pre-heating + } + return true + } - anchors.left: parent.left - anchors.leftMargin: UM.Theme.getSize("setting_unit_margin").width - anchors.right: parent.right - anchors.verticalCenter: parent.verticalCenter - - renderType: Text.NativeRendering - } - } - - Row - { - Button - { - id: sendCustomCommandButton + // style + color: !enabled ? UM.Theme.getColor("setting_control_disabled") : UM.Theme.getColor("setting_validation_ok") + border.width: UM.Theme.getSize("default_lining").width + border.color: !enabled ? UM.Theme.getColor("setting_control_disabled_border") : customCommandControlMouseArea.containsMouse ? UM.Theme.getColor("setting_control_border_highlight") : UM.Theme.getColor("setting_control_border") + // size + width: UM.Theme.getSize("setting_control").width height: UM.Theme.getSize("setting_control").height - anchors.right: parent.right - anchors.bottom: parent.bottom - anchors.margins: UM.Theme.getSize("default_margin").width + // highlight + Rectangle + { + anchors.fill: parent + anchors.margins: UM.Theme.getSize("default_lining").width + color: UM.Theme.getColor("setting_control_highlight") + opacity: customCommandControl.hovered ? 1.0 : 0 + } - onClicked: { - printerModel.sendCustomCommand(customCommandInput.text) + // cursor hover popup + MouseArea + { + id: customCommandControlMouseArea + hoverEnabled: true + anchors.fill: parent + cursorShape: Qt.IBeamCursor + + onHoveredChanged: + { + if (containsMouse) { + base.showTooltip( + base, + { x: 0, y: customCommandControlMouseArea.mapToItem(base, 0, 0).y }, + catalog.i18nc("@tooltip of G-code command input", "Send a custom G-code command to the connected printer. Press 'enter' to send the command.") + ) + } else { + base.hideTooltip() + } + } + } + + TextInput + { + id: customCommandControlInput + + // style + font: UM.Theme.getFont("default") + color: !enabled ? UM.Theme.getColor("setting_control_disabled_text") : UM.Theme.getColor("setting_control_text") + selectByMouse: true + clip: true + enabled: parent.enabled + renderType: Text.NativeRendering + + // anchors + anchors.left: parent.left + anchors.leftMargin: UM.Theme.getSize("setting_unit_margin").width + anchors.right: parent.right + anchors.verticalCenter: parent.verticalCenter + + // send the command when pressing enter + // we also clear the text field + Keys.onReturnPressed: + { + printerModel.sendCustomCommand(customCommandControlInput.text) + customCommandControlInput.text = "" + } } } } From 877032584e5fa0e3d0b64dd47b63e45bc95ce511 Mon Sep 17 00:00:00 2001 From: Ghostkeeper Date: Tue, 20 Mar 2018 13:22:18 +0100 Subject: [PATCH 6/6] Correct documentation This code was obviously copied from the pre-heat functionality. Let's fix the code duplication next as far as possible. Contributes to issue CURA-4879. --- resources/qml/PrinterOutput/ManualPrinterControl.qml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/resources/qml/PrinterOutput/ManualPrinterControl.qml b/resources/qml/PrinterOutput/ManualPrinterControl.qml index 777213811e..70961a2eb2 100644 --- a/resources/qml/PrinterOutput/ManualPrinterControl.qml +++ b/resources/qml/PrinterOutput/ManualPrinterControl.qml @@ -460,13 +460,13 @@ Item visible: printerModel != null ? printerModel.canSendRawGcode: true enabled: { if (printerModel == null) { - return false // Can't preheat if not connected + return false // Can't send custom commands if not connected. } if (!connectedPrinter.acceptsCommands) { return false // Not allowed to do anything } if (connectedPrinter.jobState == "printing" || connectedPrinter.jobState == "pre_print" || connectedPrinter.jobState == "resuming" || connectedPrinter.jobState == "pausing" || connectedPrinter.jobState == "paused" || connectedPrinter.jobState == "error" || connectedPrinter.jobState == "offline") { - return false // Printer is in a state where it can't react to pre-heating + return false // Printer is in a state where it can't react to custom commands. } return true }