From 6adf05bbf054a87316fa283e10ee7d8367bb787e Mon Sep 17 00:00:00 2001 From: Remco Burema Date: Fri, 9 Sep 2022 11:05:05 +0200 Subject: [PATCH] Complete interface for selecting cloud printer. CURA-9278 --- .../Machines/Models/CompatibleMachineModel.py | 21 ++----- .../src/Cloud/AbstractCloudOutputDevice.py | 29 +++++----- resources/qml/Dialogs/ChoosePrinterDialog.qml | 56 ++++++++++++++++++- .../qml/PrinterSelector/PrintSelectorCard.qml | 9 ++- 4 files changed, 83 insertions(+), 32 deletions(-) diff --git a/cura/Machines/Models/CompatibleMachineModel.py b/cura/Machines/Models/CompatibleMachineModel.py index 5526c67331..1ac13d4ad4 100644 --- a/cura/Machines/Models/CompatibleMachineModel.py +++ b/cura/Machines/Models/CompatibleMachineModel.py @@ -1,24 +1,18 @@ # Copyright (c) 2022 Ultimaker B.V. # Cura is released under the terms of the LGPLv3 or higher. -# TODO?: documentation - -from typing import Optional, Dict, cast +from typing import Optional from PyQt6.QtCore import Qt, QObject, pyqtSlot, pyqtProperty, pyqtSignal +from UM.Logger import Logger from UM.Qt.ListModel import ListModel -from UM.Settings.ContainerStack import ContainerStack from UM.i18n import i18nCatalog -from UM.Util import parseBool - -from cura.Settings.CuraContainerRegistry import CuraContainerRegistry -from cura.Settings.ExtruderStack import ExtruderStack class CompatibleMachineModel(ListModel): NameRole = Qt.ItemDataRole.UserRole + 1 - IdRole = Qt.ItemDataRole.UserRole + 2 + UniqueIdRole = Qt.ItemDataRole.UserRole + 2 ExtrudersRole = Qt.ItemDataRole.UserRole + 3 def __init__(self, parent: Optional[QObject] = None) -> None: @@ -27,7 +21,7 @@ class CompatibleMachineModel(ListModel): self._catalog = i18nCatalog("cura") self.addRoleName(self.NameRole, "name") - self.addRoleName(self.IdRole, "id") + self.addRoleName(self.UniqueIdRole, "unique_id") self.addRoleName(self.ExtrudersRole, "extruders") self._update() @@ -62,11 +56,10 @@ class CompatibleMachineModel(ListModel): # add currently inactive, but possible materials: for configuration in printer.availableConfigurations: - print(" CONFIG !") for extruder in configuration.extruderConfigurations: if not extruder.position in extruder_configs: - # TODO: log -- all extruders should be present in the init round, regardless of if a material was active + Logger.log("w", f"No active extruder for position {extruder.position}.") continue extruder_configs[extruder.position]["materials"].append({ @@ -77,8 +70,6 @@ class CompatibleMachineModel(ListModel): self.appendItem({ "name": printer.name, - "id": printer.uniqueName, + "unique_id": printer.uniqueName, "extruders": [extruder for extruder in extruder_configs.values()] }) - - # TODO: Handle 0 compatible machines -> option to close window? Message in card? (remember the design has a refresh button!) diff --git a/plugins/UM3NetworkPrinting/src/Cloud/AbstractCloudOutputDevice.py b/plugins/UM3NetworkPrinting/src/Cloud/AbstractCloudOutputDevice.py index e8f652064d..7384cf784f 100644 --- a/plugins/UM3NetworkPrinting/src/Cloud/AbstractCloudOutputDevice.py +++ b/plugins/UM3NetworkPrinting/src/Cloud/AbstractCloudOutputDevice.py @@ -1,7 +1,7 @@ from time import time from typing import List, Optional -from PyQt6.QtCore import QObject +from PyQt6.QtCore import QObject, pyqtSlot from PyQt6.QtNetwork import QNetworkReply from UM import i18nCatalog @@ -48,7 +48,6 @@ class AbstractCloudOutputDevice(UltimakerNetworkedPrinterOutputDevice): Logger.log("i", "Attempting to connect AbstractCloudOutputDevice %s", self.key) super().connect() - #CuraApplication.getInstance().getBackend().backendStateChange.connect(self._onBackendStateChange) self._update() def disconnect(self) -> None: @@ -91,26 +90,28 @@ class AbstractCloudOutputDevice(UltimakerNetworkedPrinterOutputDevice): self._updatePrinters(all_configurations) def _onError(self, reply: QNetworkReply, error: QNetworkReply.NetworkError) -> None: - # TODO! + Logger.log("w", f"Failed to get clusters by machine type: {str(error)}.") + + @pyqtSlot(str) + def printerSelected(self, unique_id: str): + print(unique_id) + if self._on_print_dialog: + self._on_print_dialog.close() + + @pyqtSlot() + def refresh(self): + print("-REFRESH-") pass - def _openChoosePrinterDialog(self, machine_filter_id: str) -> None: + def _openChoosePrinterDialog(self) -> None: if self._on_print_dialog is None: qml_path = Resources.getPath(CuraApplication.ResourceTypes.QmlFiles, "Dialogs", "ChoosePrinterDialog.qml") self._on_print_dialog = CuraApplication.getInstance().createQmlComponent(qml_path, {}) if self._on_print_dialog is None: # Failed to load QML file. return - self._on_print_dialog.setProperty("machine_id_filter", machine_filter_id) + self._on_print_dialog.setProperty("manager", self) self._on_print_dialog.show() def requestWrite(self, nodes: List[SceneNode], file_name: Optional[str] = None, limit_mimetypes: bool = False, file_handler: Optional[FileHandler] = None, **kwargs) -> None: - - # TODO: - # - Prettify (and make usable) dialog. - # (Including extruders... their metadata is already in the model. Is that enough though. Does that contain configurations as well?) - # - On button clicked, fetch/push to here selected printer, hide dialog - # - Find correct output-device for selected printer maybe via `CuraApplication.getInstance().getOutputDeviceManager().getOutputDevices()` - # Call 'requestWrite' of the selected output-device. - - self._openChoosePrinterDialog(CuraApplication.getInstance().getGlobalContainerStack().definition.getId()) + self._openChoosePrinterDialog() diff --git a/resources/qml/Dialogs/ChoosePrinterDialog.qml b/resources/qml/Dialogs/ChoosePrinterDialog.qml index fbaf9a61bb..b7079fcabd 100644 --- a/resources/qml/Dialogs/ChoosePrinterDialog.qml +++ b/resources/qml/Dialogs/ChoosePrinterDialog.qml @@ -10,19 +10,65 @@ import Cura 1.0 as Cura UM.Dialog { + property var manager + id: base + title: catalog.i18nc("@title:window", "Select Printer") + backgroundColor: UM.Theme.getColor("background_2") - property string machine_id_filter: "" + width: minimumWidth + minimumWidth: 550 * screenScaleFactor + height: minimumHeight + minimumHeight: 550 * screenScaleFactor + + modality: Qt.ApplicationModal + ScrollView { + // Workaround for Windowing bugs in Qt: + width: 550 * screenScaleFactor - 3 * UM.Theme.getSize("default_margin").width + height: 550 * screenScaleFactor - 3 * UM.Theme.getSize("default_margin").height + + UM.I18nCatalog + { + id: catalog + name: "cura" + } + anchors.fill: parent Column { anchors.fill: parent spacing: UM.Theme.getSize("default_margin").height + Item + { + width: parent.width + height: childrenRect.height + + UM.Label + { + anchors.left: parent.left + text: catalog.i18nc("@title:label", "Compatible Printers") + font: UM.Theme.getFont("large") + } + + UM.SimpleButton + { + anchors.right: parent.right + + width: UM.Theme.getSize("small_button").width + height: UM.Theme.getSize("small_button").height + iconSource: UM.Theme.getIcon("ArrowDoubleCircleRight") + color: UM.Theme.getColor("text_link") + hoverColor: UM.Theme.getColor("text_scene_hover") + + onClicked: manager.refresh() + } + } + Repeater { id: contents @@ -32,9 +78,17 @@ UM.Dialog delegate: Cura.PrintSelectorCard { name: model.name + unique_id: model.unique_id extruders: model.extruders + manager: base.manager } } + + UM.Label + { + visible: contents.count < 1 + text: catalog.i18nc("@description", "No compatible printers, that are currently online, where found.") + } } } } diff --git a/resources/qml/PrinterSelector/PrintSelectorCard.qml b/resources/qml/PrinterSelector/PrintSelectorCard.qml index 040f12642b..29c17bc61e 100644 --- a/resources/qml/PrinterSelector/PrintSelectorCard.qml +++ b/resources/qml/PrinterSelector/PrintSelectorCard.qml @@ -11,7 +11,9 @@ import Cura 1.0 as Cura Rectangle { property alias name: printerTitle.text + property string unique_id property var extruders + property var manager width: parent.width height: childrenRect.height + 2 * UM.Theme.getSize("default_margin").height @@ -63,7 +65,7 @@ Rectangle id: extruderIcon anchors.top: parent.top anchors.left: parent.left - materialColor: modelData.materials.length == 1 ? modelData.materials[0].color : "white" + materialColor: modelData.materials.length == 1 ? modelData.materials[0].hexcolor : "white" iconSize: UM.Theme.getSize("medium_button_icon").width } @@ -82,6 +84,7 @@ Rectangle id: singleMaterialText anchors.left: extruderCore.right anchors.verticalCenter: extruderCore.verticalCenter + anchors.leftMargin: UM.Theme.getSize("default_margin").width text: modelData.materials.length == 1 ? modelData.materials[0].brand + " " + modelData.materials[0].name : "" visible: modelData.materials.length == 1 } @@ -119,7 +122,7 @@ Rectangle { border.width: UM.Theme.getSize("default_lining").width border.color: UM.Theme.getColor("border_accent_1") - color: control.hovered ? UM.Theme.getColor("toolbar_button_hover"): UM.Theme.getColor("background_1") + color: printButton.hovered ? UM.Theme.getColor("toolbar_button_hover"): UM.Theme.getColor("background_1") } contentItem: Item @@ -133,6 +136,8 @@ Rectangle height: width } } + + onClicked: manager.printerSelected(unique_id) } } }