From 2bcbe9400893905a824c83ea0ad08655dd39d0f0 Mon Sep 17 00:00:00 2001 From: Victor Lin <60565737+v-xup6@users.noreply.github.com> Date: Wed, 21 Apr 2021 15:35:08 +0800 Subject: [PATCH 01/96] Standard Atom 2.0 --- resources/definitions/atom2.def.json | 40 ++++++++++++++++++++++++++++ 1 file changed, 40 insertions(+) create mode 100644 resources/definitions/atom2.def.json diff --git a/resources/definitions/atom2.def.json b/resources/definitions/atom2.def.json new file mode 100644 index 0000000000..bc19ce49ef --- /dev/null +++ b/resources/definitions/atom2.def.json @@ -0,0 +1,40 @@ +{ + "name": "Atom 2", + "version": 2, + "inherits": "fdmprinter", + "metadata": + { + "visible": true, + "author": "Victor (Yu Chieh) Lin", + "manufacturer": "Layer One", + "file_formats": "text/x-gcode", + "platform_offset": [ 0, 0, 0 ], + "machine_extruder_trains": + { + "0": "atom2_extruder_0" + } + }, + + "overrides": { + "machine_name": { "default_value": "Atom 2" }, + "machine_shape": { "default_value": "elliptic" }, + "machine_width": { "default_value": 210 }, + "machine_depth": { "default_value": 210 }, + "machine_height": { "default_value": 320 }, + "machine_extruder_count": { "default_value": 1 }, + "machine_heated_bed": { "default_value": false }, + "machine_center_is_zero": { "default_value": true }, + "machine_gcode_flavor": { "default_value": "RepRap (Marlin/Sprinter)" }, + + "machine_start_gcode": { + "default_value": "G21\nG90 \nM107\nG28\nG92 E0\nG1 F200 E3\nG92 E0" + }, + "machine_end_gcode": { + "default_value": "M104 S0\nG28\nG91\nG1 E-6 F300\nM84\nG90" + }, + + "layer_height": { "default_value": 0.2 }, + "default_material_print_temperature": { "default_value": 200 }, + "speed_print": { "default_value": 30 } + } +} \ No newline at end of file From 420fe2ab3309a6666ef36d00b9daf74d1954fe02 Mon Sep 17 00:00:00 2001 From: Victor Lin <60565737+v-xup6@users.noreply.github.com> Date: Wed, 21 Apr 2021 15:36:07 +0800 Subject: [PATCH 02/96] Single Extruder - Atom 2.0 --- resources/extruders/atom2_extruder_0.def.json | 15 +++++++++++++++ 1 file changed, 15 insertions(+) create mode 100644 resources/extruders/atom2_extruder_0.def.json diff --git a/resources/extruders/atom2_extruder_0.def.json b/resources/extruders/atom2_extruder_0.def.json new file mode 100644 index 0000000000..50e1f8501f --- /dev/null +++ b/resources/extruders/atom2_extruder_0.def.json @@ -0,0 +1,15 @@ +{ + "version": 2, + "name": "Extruder 1", + "inherits": "fdmextruder", + "metadata": { + "machine": "Atom 2", + "position": "0" + }, + + "overrides": { + "extruder_nr": { "default_value": 0 }, + "machine_nozzle_size": { "default_value": 0.4 }, + "material_diameter": { "default_value": 1.75 } + } +} From 781a5d42a6539ecdb995752ce0c957b85b4a8d01 Mon Sep 17 00:00:00 2001 From: Victor Lin <60565737+v-xup6@users.noreply.github.com> Date: Wed, 21 Apr 2021 16:37:37 +0800 Subject: [PATCH 03/96] Update Atom 2.0 --- resources/definitions/atom2.def.json | 55 +++++++++++++++++++++------- 1 file changed, 42 insertions(+), 13 deletions(-) diff --git a/resources/definitions/atom2.def.json b/resources/definitions/atom2.def.json index bc19ce49ef..2fd76df8fe 100644 --- a/resources/definitions/atom2.def.json +++ b/resources/definitions/atom2.def.json @@ -2,16 +2,13 @@ "name": "Atom 2", "version": 2, "inherits": "fdmprinter", - "metadata": - { + "metadata": { "visible": true, "author": "Victor (Yu Chieh) Lin", "manufacturer": "Layer One", "file_formats": "text/x-gcode", - "platform_offset": [ 0, 0, 0 ], - "machine_extruder_trains": - { - "0": "atom2_extruder_0" + "platform_offset": [0,0,0], + "machine_extruder_trains": { "0": "atom2_extruder_0" } }, @@ -26,15 +23,47 @@ "machine_center_is_zero": { "default_value": true }, "machine_gcode_flavor": { "default_value": "RepRap (Marlin/Sprinter)" }, - "machine_start_gcode": { - "default_value": "G21\nG90 \nM107\nG28\nG92 E0\nG1 F200 E3\nG92 E0" - }, - "machine_end_gcode": { - "default_value": "M104 S0\nG28\nG91\nG1 E-6 F300\nM84\nG90" - }, + "machine_start_gcode": { "default_value": "G21\nG90 \nM107\nG28\nG92 E0\nG1 F200 E3\nG92 E0" }, + "machine_end_gcode": { "default_value": "M104 S0\nG28\nG91\nG1 E-6 F300\nM84\nG90" }, "layer_height": { "default_value": 0.2 }, "default_material_print_temperature": { "default_value": 200 }, - "speed_print": { "default_value": 30 } + "speed_print": { "default_value": 32 }, + "infill_before_walls": { "value": false }, + "optimize_wall_printing_order": { "value": "True" }, + "infill_sparse_density": { "default_value": 10 }, + "brim_width": + { + "label": "Brim Width", + "description": "The distance from the model to the outermost brim line. A larger brim enhances adhesion to the build plate, but also reduces the effective print area.", + "type": "float", + "unit": "mm", + "default_value": 4, + "minimum_value": "0.0", + "maximum_value_warning": "50.0", + "maximum_value": "0.5 * min(machine_width, machine_depth)", + "enabled": "resolveOrValue('adhesion_type') == 'brim' or resolveOrValue('prime_tower_brim_enable')", + "settable_per_mesh": false, + "settable_per_extruder": true, + "limit_to_extruder": "atom2_extruder_0", + "children": + { + "brim_line_count": + { + "label": "Brim Line Count", + "description": "The number of lines used for a brim. More brim lines enhance adhesion to the build plate, but also reduces the effective print area.", + "type": "int", + "default_value": 10, + "minimum_value": "0", + "maximum_value_warning": "50 / skirt_brim_line_width", + "maximum_value": "0.5 * min(machine_width, machine_depth) / skirt_brim_line_width", + "value": 10, + "enabled": "resolveOrValue('adhesion_type') == 'brim' or resolveOrValue('prime_tower_brim_enable')", + "settable_per_mesh": false, + "settable_per_extruder": true, + "limit_to_extruder": "atom2_extruder_0" + } + } + } } } \ No newline at end of file From d5f845831fa90f3bc496d48a8c0e37dd1ad1cb42 Mon Sep 17 00:00:00 2001 From: Victor Lin <60565737+v-xup6@users.noreply.github.com> Date: Thu, 22 Apr 2021 17:07:47 +0800 Subject: [PATCH 04/96] Added Atom Plus --- resources/definitions/atom2.def.json | 2 +- resources/definitions/atomPlus.def.json | 35 +++++++++++++++++++++++++ 2 files changed, 36 insertions(+), 1 deletion(-) create mode 100644 resources/definitions/atomPlus.def.json diff --git a/resources/definitions/atom2.def.json b/resources/definitions/atom2.def.json index 2fd76df8fe..3918631699 100644 --- a/resources/definitions/atom2.def.json +++ b/resources/definitions/atom2.def.json @@ -21,7 +21,7 @@ "machine_extruder_count": { "default_value": 1 }, "machine_heated_bed": { "default_value": false }, "machine_center_is_zero": { "default_value": true }, - "machine_gcode_flavor": { "default_value": "RepRap (Marlin/Sprinter)" }, + "machine_gcode_flavor": { "RepRap (Marlin/Sprinter)": "Marlin" }, "machine_start_gcode": { "default_value": "G21\nG90 \nM107\nG28\nG92 E0\nG1 F200 E3\nG92 E0" }, "machine_end_gcode": { "default_value": "M104 S0\nG28\nG91\nG1 E-6 F300\nM84\nG90" }, diff --git a/resources/definitions/atomPlus.def.json b/resources/definitions/atomPlus.def.json new file mode 100644 index 0000000000..1726fee8eb --- /dev/null +++ b/resources/definitions/atomPlus.def.json @@ -0,0 +1,35 @@ +{ + "name": "Atom Plus", + "version": 2, + "inherits": "fdmprinter", + "metadata": { + "visible": true, + "author": "Victor (Yu Chieh) Lin", + "manufacturer": "Layer One", + "file_formats": "text/x-gcode", + "platform_offset": [0,0,0], + "machine_extruder_trains": { "0": "atomPlus_extruder_0" + } + }, + + "overrides": { + "machine_name": { "default_value": "Atom Plus" }, + "machine_shape": { "default_value": "elliptic" }, + "machine_width": { "default_value": 420 }, + "machine_depth": { "default_value": 420 }, + "machine_height": { "default_value": 910 }, + "machine_extruder_count": { "default_value": 1 }, + "machine_heated_bed": { "default_value": false }, + "machine_center_is_zero": { "default_value": true }, + "machine_gcode_flavor": { "RepRap (Marlin/Sprinter)": "Marlin" }, + + "machine_start_gcode": { "default_value": "G21\nG90 \nM107\nG28\nG92 E0\nG1 F200 E3\nG92 E0" }, + "machine_end_gcode": { "default_value": "M104 S0\nG28\nG91\nG1 E-6 F300\nM84\nG90" }, + + "layer_height": { "default_value": 0.4 }, + "default_material_print_temperature": { "default_value": 220 }, + "speed_print": { "default_value": 32 }, + "optimize_wall_printing_order": { "value": "True" }, + "infill_sparse_density": { "default_value": 10 } + } +} \ No newline at end of file From 54f41b964169acdf4edc45cb2306f0eaf6a45cbc Mon Sep 17 00:00:00 2001 From: Victor Lin <60565737+v-xup6@users.noreply.github.com> Date: Thu, 22 Apr 2021 17:11:03 +0800 Subject: [PATCH 05/96] Extruder for Atom Plus (1mm) --- resources/extruders/atomPlus_extruder_0.def.json | 15 +++++++++++++++ 1 file changed, 15 insertions(+) create mode 100644 resources/extruders/atomPlus_extruder_0.def.json diff --git a/resources/extruders/atomPlus_extruder_0.def.json b/resources/extruders/atomPlus_extruder_0.def.json new file mode 100644 index 0000000000..7a76eada02 --- /dev/null +++ b/resources/extruders/atomPlus_extruder_0.def.json @@ -0,0 +1,15 @@ +{ + "version": 2, + "name": "Extruder 1", + "inherits": "fdmextruder", + "metadata": { + "machine": "Atom Plus", + "position": "0" + }, + + "overrides": { + "extruder_nr": { "default_value": 0 }, + "machine_nozzle_size": { "default_value": 1 }, + "material_diameter": { "default_value": 1.75 } + } +} From 1dab6e39e11840313e5cb65b318dd8ef72b28637 Mon Sep 17 00:00:00 2001 From: Victor Lin <60565737+v-xup6@users.noreply.github.com> Date: Thu, 29 Apr 2021 22:31:53 +0800 Subject: [PATCH 06/96] Match ID for Atom2 Co-authored-by: Jaime van Kessel --- resources/extruders/atom2_extruder_0.def.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/resources/extruders/atom2_extruder_0.def.json b/resources/extruders/atom2_extruder_0.def.json index 50e1f8501f..be9d5782ff 100644 --- a/resources/extruders/atom2_extruder_0.def.json +++ b/resources/extruders/atom2_extruder_0.def.json @@ -3,7 +3,7 @@ "name": "Extruder 1", "inherits": "fdmextruder", "metadata": { - "machine": "Atom 2", + "machine": "atom2", "position": "0" }, From fbd2b45dd0591db348cb9a9485ac7adf1824d4c3 Mon Sep 17 00:00:00 2001 From: Victor Lin <60565737+v-xup6@users.noreply.github.com> Date: Thu, 29 Apr 2021 22:32:22 +0800 Subject: [PATCH 07/96] Match ID for atomPlus Co-authored-by: Jaime van Kessel --- resources/extruders/atomPlus_extruder_0.def.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/resources/extruders/atomPlus_extruder_0.def.json b/resources/extruders/atomPlus_extruder_0.def.json index 7a76eada02..19ab13cf79 100644 --- a/resources/extruders/atomPlus_extruder_0.def.json +++ b/resources/extruders/atomPlus_extruder_0.def.json @@ -3,7 +3,7 @@ "name": "Extruder 1", "inherits": "fdmextruder", "metadata": { - "machine": "Atom Plus", + "machine": "atomPlus", "position": "0" }, From d089bf16cd22cdeb121672b9c445c27b17b4e8be Mon Sep 17 00:00:00 2001 From: Victor Lin <60565737+v-xup6@users.noreply.github.com> Date: Wed, 5 May 2021 11:54:55 +0800 Subject: [PATCH 08/96] Add files via upload Minor tweaks --- resources/definitions/atom2.def.json | 10 ++-------- resources/definitions/atomPlus.def.json | 1 - 2 files changed, 2 insertions(+), 9 deletions(-) diff --git a/resources/definitions/atom2.def.json b/resources/definitions/atom2.def.json index 3918631699..8fbbe2c698 100644 --- a/resources/definitions/atom2.def.json +++ b/resources/definitions/atom2.def.json @@ -21,15 +21,13 @@ "machine_extruder_count": { "default_value": 1 }, "machine_heated_bed": { "default_value": false }, "machine_center_is_zero": { "default_value": true }, - "machine_gcode_flavor": { "RepRap (Marlin/Sprinter)": "Marlin" }, "machine_start_gcode": { "default_value": "G21\nG90 \nM107\nG28\nG92 E0\nG1 F200 E3\nG92 E0" }, "machine_end_gcode": { "default_value": "M104 S0\nG28\nG91\nG1 E-6 F300\nM84\nG90" }, "layer_height": { "default_value": 0.2 }, - "default_material_print_temperature": { "default_value": 200 }, + "default_material_print_temperature": { "default_value": 210 }, "speed_print": { "default_value": 32 }, - "infill_before_walls": { "value": false }, "optimize_wall_printing_order": { "value": "True" }, "infill_sparse_density": { "default_value": 10 }, "brim_width": @@ -44,8 +42,6 @@ "maximum_value": "0.5 * min(machine_width, machine_depth)", "enabled": "resolveOrValue('adhesion_type') == 'brim' or resolveOrValue('prime_tower_brim_enable')", "settable_per_mesh": false, - "settable_per_extruder": true, - "limit_to_extruder": "atom2_extruder_0", "children": { "brim_line_count": @@ -59,9 +55,7 @@ "maximum_value": "0.5 * min(machine_width, machine_depth) / skirt_brim_line_width", "value": 10, "enabled": "resolveOrValue('adhesion_type') == 'brim' or resolveOrValue('prime_tower_brim_enable')", - "settable_per_mesh": false, - "settable_per_extruder": true, - "limit_to_extruder": "atom2_extruder_0" + "settable_per_mesh": false } } } diff --git a/resources/definitions/atomPlus.def.json b/resources/definitions/atomPlus.def.json index 1726fee8eb..2d053693ff 100644 --- a/resources/definitions/atomPlus.def.json +++ b/resources/definitions/atomPlus.def.json @@ -21,7 +21,6 @@ "machine_extruder_count": { "default_value": 1 }, "machine_heated_bed": { "default_value": false }, "machine_center_is_zero": { "default_value": true }, - "machine_gcode_flavor": { "RepRap (Marlin/Sprinter)": "Marlin" }, "machine_start_gcode": { "default_value": "G21\nG90 \nM107\nG28\nG92 E0\nG1 F200 E3\nG92 E0" }, "machine_end_gcode": { "default_value": "M104 S0\nG28\nG91\nG1 E-6 F300\nM84\nG90" }, From f82384d93c445cee18a9b5f20161cb80519a2d50 Mon Sep 17 00:00:00 2001 From: Ghostkeeper Date: Thu, 24 Jun 2021 14:20:38 +0200 Subject: [PATCH 09/96] Revert "Revert CURA-8055 in the 4.10 branch. This should not have been merged in there." This reverts commit 4d29de45796dc42f76c774a216a0601bb57cf790. Effectively this re-applies the changes for CURA-8055 / #9957. --- .../Models/MaterialManagementModel.py | 57 ++++++++++++++++++- cura/Settings/GlobalStack.py | 8 +++ .../ultimaker2_plus_connect.def.json | 3 +- resources/definitions/ultimaker_s3.def.json | 1 + resources/definitions/ultimaker_s5.def.json | 1 + .../Preferences/Materials/MaterialsPage.qml | 32 ++++++++++- 6 files changed, 98 insertions(+), 4 deletions(-) diff --git a/cura/Machines/Models/MaterialManagementModel.py b/cura/Machines/Models/MaterialManagementModel.py index cd35a78353..85f208d8b0 100644 --- a/cura/Machines/Models/MaterialManagementModel.py +++ b/cura/Machines/Models/MaterialManagementModel.py @@ -2,9 +2,10 @@ # Cura is released under the terms of the LGPLv3 or higher. import copy # To duplicate materials. -from PyQt5.QtCore import QObject, pyqtSignal, pyqtSlot # To allow the preference page proxy to be used from the actual preferences page. +from PyQt5.QtCore import pyqtProperty, pyqtSignal, pyqtSlot, QObject, QUrl from typing import Any, Dict, Optional, TYPE_CHECKING import uuid # To generate new GUIDs for new materials. +import zipfile # To export all materials in a .zip archive. from UM.i18n import i18nCatalog from UM.Logger import Logger @@ -24,6 +25,11 @@ class MaterialManagementModel(QObject): This class handles the actions in that page, such as creating new materials, renaming them, etc. """ + def __init__(self, parent: QObject) -> None: + super().__init__(parent) + cura_application = cura.CuraApplication.CuraApplication.getInstance() + self._preferred_export_all_path = None # type: Optional[QUrl] # Path to export all materials to. None if not yet initialised. + cura_application.getOutputDeviceManager().outputDevicesChanged.connect(self._onOutputDevicesChanged) favoritesChanged = pyqtSignal(str) """Triggered when a favorite is added or removed. @@ -264,3 +270,52 @@ class MaterialManagementModel(QObject): self.favoritesChanged.emit(material_base_file) except ValueError: # Material was not in the favorites list. Logger.log("w", "Material {material_base_file} was already not a favorite material.".format(material_base_file = material_base_file)) + + def _onOutputDevicesChanged(self) -> None: + """ + When the list of output devices changes, we may want to update the + preferred export path. + """ + cura_application = cura.CuraApplication.CuraApplication.getInstance() + device_manager = cura_application.getOutputDeviceManager() + devices = device_manager.getOutputDevices() + for device in devices: + if device.__class__.__name__ == "RemovableDriveOutputDevice": + self._preferred_export_all_path = QUrl.fromLocalFile(device.getId()) + break + else: # No removable drives? Use local path. + self._preferred_export_all_path = cura_application.getDefaultPath("dialog_material_path") + self.outputDevicesChanged.emit() + + outputDevicesChanged = pyqtSignal() # Triggered when adding or removing removable drives. + @pyqtProperty(QUrl, notify = outputDevicesChanged) + def preferredExportAllPath(self) -> QUrl: + """ + Get the preferred path to export materials to. + + If there is a removable drive, that should be the preferred path. Otherwise it should be the most recent local + file path. + :return: The preferred path to export all materials to. + """ + if self._preferred_export_all_path is None: # Not initialised yet. Can happen when output devices changed before class got created. + self._onOutputDevicesChanged() + return self._preferred_export_all_path + + @pyqtSlot(QUrl) + def exportAll(self, file_path: QUrl) -> None: + """ + Export all materials to a certain file path. + :param file_path: The path to export the materials to. + """ + registry = CuraContainerRegistry.getInstance() + + archive = zipfile.ZipFile(file_path.toLocalFile(), "w", compression = zipfile.ZIP_DEFLATED) + for metadata in registry.findInstanceContainersMetadata(type = "material"): + if metadata["base_file"] != metadata["id"]: # Only process base files. + continue + if metadata["id"] == "empty_material": # Don't export the empty material. + continue + material = registry.findContainers(id = metadata["id"])[0] + suffix = registry.getMimeTypeForContainer(type(material)).preferredSuffix + filename = metadata["id"] + "." + suffix + archive.writestr(filename, material.serialize()) diff --git a/cura/Settings/GlobalStack.py b/cura/Settings/GlobalStack.py index 2c7cbf5e25..282034c0ee 100755 --- a/cura/Settings/GlobalStack.py +++ b/cura/Settings/GlobalStack.py @@ -86,6 +86,14 @@ class GlobalStack(CuraContainerStack): def supportsNetworkConnection(self): return self.getMetaDataEntry("supports_network_connection", False) + @pyqtProperty(bool, constant = True) + def supportsMaterialExport(self): + """ + Whether the printer supports Cura's export format of material profiles. + :return: ``True`` if it supports it, or ``False`` if not. + """ + return self.getMetaDataEntry("supports_material_export", False) + @classmethod def getLoadingPriority(cls) -> int: return 2 diff --git a/resources/definitions/ultimaker2_plus_connect.def.json b/resources/definitions/ultimaker2_plus_connect.def.json index c0ddcf813f..46c615a262 100644 --- a/resources/definitions/ultimaker2_plus_connect.def.json +++ b/resources/definitions/ultimaker2_plus_connect.def.json @@ -22,7 +22,8 @@ "0": "ultimaker2_plus_connect_extruder_0" }, "supports_usb_connection": false, - "supports_network_connection": true + "supports_network_connection": true, + "supports_material_export": true }, "overrides": { diff --git a/resources/definitions/ultimaker_s3.def.json b/resources/definitions/ultimaker_s3.def.json index 962bff3fa0..43f32a96dc 100644 --- a/resources/definitions/ultimaker_s3.def.json +++ b/resources/definitions/ultimaker_s3.def.json @@ -27,6 +27,7 @@ "first_start_actions": [ "DiscoverUM3Action" ], "supported_actions": [ "DiscoverUM3Action" ], "supports_usb_connection": false, + "supports_material_export": true, "weight": -1, "firmware_update_info": { "id": 213482, diff --git a/resources/definitions/ultimaker_s5.def.json b/resources/definitions/ultimaker_s5.def.json index 8a9880c31a..71de826953 100644 --- a/resources/definitions/ultimaker_s5.def.json +++ b/resources/definitions/ultimaker_s5.def.json @@ -28,6 +28,7 @@ "supported_actions": [ "DiscoverUM3Action" ], "supports_usb_connection": false, "supports_network_connection": true, + "supports_material_export": true, "weight": -2, "firmware_update_info": { "id": 9051, diff --git a/resources/qml/Preferences/Materials/MaterialsPage.qml b/resources/qml/Preferences/Materials/MaterialsPage.qml index 791d6685de..8d6dfdfb3a 100644 --- a/resources/qml/Preferences/Materials/MaterialsPage.qml +++ b/resources/qml/Preferences/Materials/MaterialsPage.qml @@ -1,5 +1,5 @@ -// Copyright (c) 2018 Ultimaker B.V. -// Uranium is released under the terms of the LGPLv3 or higher. +// Copyright (c) 2021 Ultimaker B.V. +// Cura is released under the terms of the LGPLv3 or higher. import QtQuick 2.7 import QtQuick.Controls 1.4 @@ -191,6 +191,20 @@ Item } enabled: base.hasCurrentItem } + + //Sync button. + Button + { + id: syncMaterialsButton + text: catalog.i18nc("@action:button Sending materials to printers", "Sync with Printers") + iconName: "sync-synchronizing" + onClicked: + { + forceActiveFocus(); + exportAllMaterialsDialog.open(); + } + visible: Cura.MachineManager.activeMachine.supportsMaterialExport + } } Item { @@ -368,6 +382,20 @@ Item } } + FileDialog + { + id: exportAllMaterialsDialog + title: catalog.i18nc("@title:window", "Export All Materials") + selectExisting: false + nameFilters: ["Material archives (*.umm)", "All files (*)"] + folder: base.materialManagementModel.preferredExportAllPath + onAccepted: + { + base.materialManagementModel.exportAll(fileUrl); + CuraApplication.setDefaultPath("dialog_material_path", folder); + } + } + MessageDialog { id: messageDialog From b4a8cb1b82cb87c8315d6ca91539a9339c180677 Mon Sep 17 00:00:00 2001 From: Jaime van Kessel Date: Thu, 8 Jul 2021 17:01:03 +0200 Subject: [PATCH 10/96] Add monitor print button for cloud print The button redirects the user to the cloud page CURA-8018 --- .../UM3NetworkPrinting/src/Cloud/CloudOutputDevice.py | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/plugins/UM3NetworkPrinting/src/Cloud/CloudOutputDevice.py b/plugins/UM3NetworkPrinting/src/Cloud/CloudOutputDevice.py index 1884efec46..9a996444a6 100644 --- a/plugins/UM3NetworkPrinting/src/Cloud/CloudOutputDevice.py +++ b/plugins/UM3NetworkPrinting/src/Cloud/CloudOutputDevice.py @@ -256,7 +256,16 @@ class CloudOutputDevice(UltimakerNetworkedPrinterOutputDevice): """ self._uploaded_print_job = self._pre_upload_print_job self._progress.hide() - PrintJobUploadSuccessMessage().show() + message = PrintJobUploadSuccessMessage() + message.addAction("monitor print", + name=I18N_CATALOG.i18nc("@action:button", "Monitor Print"), + icon="", + description="Remove the plugin", + button_align=message.ActionButtonAlignment.ALIGN_RIGHT) + df_url = "https://digitalfactory.ultimaker.com/app/jobs/%s?utm_source=cura&utm_medium=software&utm_campaign=monitor-button" % self._cluster.cluster_id + message.pyQtActionTriggered.connect(lambda message, action: (QDesktopServices.openUrl(QUrl(df_url)), message.hide())) + + message.show() self.writeFinished.emit() def _onPrintUploadSpecificError(self, reply: "QNetworkReply", _: "QNetworkReply.NetworkError"): From ffa89bb1a16380c41e05846b7bd2073d6d50f00e Mon Sep 17 00:00:00 2001 From: Ghostkeeper Date: Thu, 8 Jul 2021 16:24:23 +0200 Subject: [PATCH 11/96] Allow open file button to resize depending on content items This re-links the widths, heights and paddings such that we can later change the width of the button depending on its contents. However there is a complication: Buttons automatically change the size of the contents based on the size of the button minus its padding. So making the size of the button in turn depend on its contents causes a binding loop. To get around this binding loop, we need to manually calculate the size of the button, such that the size of the contents ends up exactly right. Contributes to issue CURA-8008. --- plugins/PrepareStage/PrepareMenu.qml | 34 +++++++++++++++++++--------- 1 file changed, 23 insertions(+), 11 deletions(-) diff --git a/plugins/PrepareStage/PrepareMenu.qml b/plugins/PrepareStage/PrepareMenu.qml index 2d3814309e..4e6c37961c 100644 --- a/plugins/PrepareStage/PrepareMenu.qml +++ b/plugins/PrepareStage/PrepareMenu.qml @@ -77,24 +77,36 @@ Item Button { id: openFileButton + + //Make the button square if the contents are. + leftPadding: topPadding + rightPadding: topPadding + bottomPadding: topPadding + height: UM.Theme.getSize("stage_menu").height - width: UM.Theme.getSize("stage_menu").height + width: openFileIconContainer.width + leftPadding + rightPadding onClicked: Cura.Actions.open.trigger() hoverEnabled: true - contentItem: Item + contentItem: Row { - anchors.fill: parent - UM.RecolorImage + Item { - id: buttonIcon - anchors.centerIn: parent - source: UM.Theme.getIcon("Folder", "medium") - width: UM.Theme.getSize("button_icon").width - height: UM.Theme.getSize("button_icon").height - color: UM.Theme.getColor("icon") + id: openFileIconContainer + height: parent.height + width: height //Square button. - sourceSize.height: height + UM.RecolorImage + { + id: buttonIcon + anchors.centerIn: parent + source: UM.Theme.getIcon("Folder", "medium") + width: UM.Theme.getSize("button_icon").width + height: UM.Theme.getSize("button_icon").height + color: UM.Theme.getColor("icon") + + sourceSize.height: height + } } } From 41642a35ffd885a6260d2dc766813884ea748bde Mon Sep 17 00:00:00 2001 From: Ghostkeeper Date: Thu, 8 Jul 2021 18:00:35 +0200 Subject: [PATCH 12/96] Add chevron to select where to load models from The chevron looks a little big now. No worries, we can fix that. Contributes to issue CURA-8008. --- plugins/PrepareStage/PrepareMenu.qml | 23 ++++++++++++++++++++--- 1 file changed, 20 insertions(+), 3 deletions(-) diff --git a/plugins/PrepareStage/PrepareMenu.qml b/plugins/PrepareStage/PrepareMenu.qml index 4e6c37961c..bf6b76360f 100644 --- a/plugins/PrepareStage/PrepareMenu.qml +++ b/plugins/PrepareStage/PrepareMenu.qml @@ -84,7 +84,7 @@ Item bottomPadding: topPadding height: UM.Theme.getSize("stage_menu").height - width: openFileIconContainer.width + leftPadding + rightPadding + width: leftPadding + openFileIconContainer.width + openFileChevronContainer.width + rightPadding onClicked: Cura.Actions.open.trigger() hoverEnabled: true @@ -105,6 +105,23 @@ Item height: UM.Theme.getSize("button_icon").height color: UM.Theme.getColor("icon") + sourceSize.height: height + } + } + Item + { + id: openFileChevronContainer + height: parent.height + width: UM.Theme.getSize("small_button_icon").width + + UM.RecolorImage + { + anchors.centerIn: parent + source: UM.Theme.getIcon("ChevronSingleDown") + width: UM.Theme.getSize("small_button_icon").width + height: UM.Theme.getSize("small_button_icon").height + color: UM.Theme.getColor("icon") + sourceSize.height: height } } @@ -113,8 +130,8 @@ Item background: Rectangle { id: background - height: UM.Theme.getSize("stage_menu").height - width: UM.Theme.getSize("stage_menu").height + height: parent.height + width: parent.width border.color: UM.Theme.getColor("lining") border.width: UM.Theme.getSize("default_lining").width From ae649d9a9f5ae6e215f4e593e9778da605203b66 Mon Sep 17 00:00:00 2001 From: Lorenzo Romagnoli Date: Fri, 9 Jul 2021 11:43:37 +0200 Subject: [PATCH 13/96] replacing with new icon for better visibility --- .../cura-light/icons/medium/ExtruderColor.svg | 14 -------------- 1 file changed, 14 deletions(-) delete mode 100644 resources/themes/cura-light/icons/medium/ExtruderColor.svg diff --git a/resources/themes/cura-light/icons/medium/ExtruderColor.svg b/resources/themes/cura-light/icons/medium/ExtruderColor.svg deleted file mode 100644 index 85360a9622..0000000000 --- a/resources/themes/cura-light/icons/medium/ExtruderColor.svg +++ /dev/null @@ -1,14 +0,0 @@ - - - - - - - - - - From 5cf7cd63f4ba18595a9672c74e82cff416a79e04 Mon Sep 17 00:00:00 2001 From: Lorenzo Romagnoli Date: Fri, 9 Jul 2021 11:45:43 +0200 Subject: [PATCH 14/96] replacing with thicker icon made the circle one pixel thicker so that the colorer ring is more visible for dark and light colors --- .../cura-light/icons/medium/ExtruderColor.svg | 14 ++++++++++++++ 1 file changed, 14 insertions(+) create mode 100644 resources/themes/cura-light/icons/medium/ExtruderColor.svg diff --git a/resources/themes/cura-light/icons/medium/ExtruderColor.svg b/resources/themes/cura-light/icons/medium/ExtruderColor.svg new file mode 100644 index 0000000000..cd4452b246 --- /dev/null +++ b/resources/themes/cura-light/icons/medium/ExtruderColor.svg @@ -0,0 +1,14 @@ + + + + + + + + + + From f4f48c0fdab65a5e520a8cf64bf677d32fbdc164 Mon Sep 17 00:00:00 2001 From: Ghostkeeper Date: Fri, 9 Jul 2021 14:23:14 +0200 Subject: [PATCH 15/96] Move padding to only be around row Not around the individual icons. This way the chevron can be placed next to the icon closer. Contributes to issue CURA-8008. --- plugins/PrepareStage/PrepareMenu.qml | 27 ++++++++++----------------- 1 file changed, 10 insertions(+), 17 deletions(-) diff --git a/plugins/PrepareStage/PrepareMenu.qml b/plugins/PrepareStage/PrepareMenu.qml index bf6b76360f..850d329ab2 100644 --- a/plugins/PrepareStage/PrepareMenu.qml +++ b/plugins/PrepareStage/PrepareMenu.qml @@ -78,35 +78,28 @@ Item { id: openFileButton - //Make the button square if the contents are. + //Make the padding such that the main icon is centred, even if something else is placed besides it. + topPadding: Math.round((parent.height - buttonIcon.height) / 2) leftPadding: topPadding rightPadding: topPadding bottomPadding: topPadding height: UM.Theme.getSize("stage_menu").height - width: leftPadding + openFileIconContainer.width + openFileChevronContainer.width + rightPadding + width: leftPadding + buttonIcon.width + openFileChevronContainer.width + rightPadding onClicked: Cura.Actions.open.trigger() hoverEnabled: true contentItem: Row { - Item + UM.RecolorImage { - id: openFileIconContainer - height: parent.height - width: height //Square button. + id: buttonIcon + source: UM.Theme.getIcon("Folder", "medium") + width: UM.Theme.getSize("button_icon").width + height: UM.Theme.getSize("button_icon").height + color: UM.Theme.getColor("icon") - UM.RecolorImage - { - id: buttonIcon - anchors.centerIn: parent - source: UM.Theme.getIcon("Folder", "medium") - width: UM.Theme.getSize("button_icon").width - height: UM.Theme.getSize("button_icon").height - color: UM.Theme.getColor("icon") - - sourceSize.height: height - } + sourceSize.height: height } Item { From 6203a5c9873ee650ff7c19a0d5688effd36a0517 Mon Sep 17 00:00:00 2001 From: Ghostkeeper Date: Fri, 9 Jul 2021 14:27:32 +0200 Subject: [PATCH 16/96] Correct chevron size and colour This is the same as what ExpandablePopup does. Contributes to issue CURA-8008. --- plugins/PrepareStage/PrepareMenu.qml | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/plugins/PrepareStage/PrepareMenu.qml b/plugins/PrepareStage/PrepareMenu.qml index 850d329ab2..323ea46050 100644 --- a/plugins/PrepareStage/PrepareMenu.qml +++ b/plugins/PrepareStage/PrepareMenu.qml @@ -110,10 +110,10 @@ Item UM.RecolorImage { anchors.centerIn: parent - source: UM.Theme.getIcon("ChevronSingleDown") - width: UM.Theme.getSize("small_button_icon").width - height: UM.Theme.getSize("small_button_icon").height - color: UM.Theme.getColor("icon") + source: UM.Theme.getIcon("ChevronSingleLeft") + width: UM.Theme.getSize("standard_arrow").width + height: UM.Theme.getSize("standard_arrow").height + color: UM.Theme.getColor("small_button_text") sourceSize.height: height } From c100ba88d0589f11d9979c08b94c48f35d605724 Mon Sep 17 00:00:00 2001 From: Ghostkeeper Date: Fri, 9 Jul 2021 15:27:12 +0200 Subject: [PATCH 17/96] Move pop-up code to external item to re-use ExpandablePopup element All of what we were about to implement is already implemented in ExpandablePopup. So let's re-use that one. That guarantees that it looks consistent too. Contributes to issue CURA-8008. --- plugins/PrepareStage/PrepareMenu.qml | 67 ++++++++++++++++------------ 1 file changed, 38 insertions(+), 29 deletions(-) diff --git a/plugins/PrepareStage/PrepareMenu.qml b/plugins/PrepareStage/PrepareMenu.qml index 323ea46050..576cd3cd95 100644 --- a/plugins/PrepareStage/PrepareMenu.qml +++ b/plugins/PrepareStage/PrepareMenu.qml @@ -1,4 +1,4 @@ -// Copyright (c) 2018 Ultimaker B.V. +// Copyright (c) 2021 Ultimaker B.V. // Cura is released under the terms of the LGPLv3 or higher. import QtQuick 2.7 @@ -36,9 +36,9 @@ Item { id: itemRow - anchors.left: openFileButton.right + anchors.left: parent.left anchors.right: parent.right - anchors.leftMargin: UM.Theme.getSize("default_margin").width + anchors.leftMargin: UM.Theme.getSize("default_margin").width + openFileButton.width + openFileMenu.width property int machineSelectorWidth: Math.round((width - printSetupSelectorItem.width) / 3) height: parent.height @@ -74,50 +74,59 @@ Item } } + //Pop-up shown when there are multiple items to select from. + Cura.ExpandablePopup + { + id: openFileMenu + contentAlignment: Cura.ExpandablePopup.ContentAlignment.AlignLeft + headerCornerSide: Cura.RoundedRectangle.Direction.All + headerPadding: Math.round((parent.height - UM.Theme.getSize("button_icon").height) / 2) + enabled: visible + + height: parent.height + width: visible ? (headerPadding * 3 + UM.Theme.getSize("button_icon").height + iconSize) : 0 + + headerItem: UM.RecolorImage + { + id: menuIcon + source: UM.Theme.getIcon("Folder", "medium") + color: UM.Theme.getColor("icon") + + sourceSize.height: height + } + + contentItem: Rectangle + { + width: 100 + height: 100 + color: "red" + } + } + + //If there is just a single item, show a button instead that directly chooses the one option. Button { id: openFileButton - //Make the padding such that the main icon is centred, even if something else is placed besides it. - topPadding: Math.round((parent.height - buttonIcon.height) / 2) - leftPadding: topPadding - rightPadding: topPadding - bottomPadding: topPadding - - height: UM.Theme.getSize("stage_menu").height - width: leftPadding + buttonIcon.width + openFileChevronContainer.width + rightPadding + height: parent.height + width: height //Square button. onClicked: Cura.Actions.open.trigger() + enabled: visible hoverEnabled: true - contentItem: Row + contentItem: Item { UM.RecolorImage { id: buttonIcon source: UM.Theme.getIcon("Folder", "medium") + anchors.centerIn: parent width: UM.Theme.getSize("button_icon").width height: UM.Theme.getSize("button_icon").height color: UM.Theme.getColor("icon") sourceSize.height: height } - Item - { - id: openFileChevronContainer - height: parent.height - width: UM.Theme.getSize("small_button_icon").width - - UM.RecolorImage - { - anchors.centerIn: parent - source: UM.Theme.getIcon("ChevronSingleLeft") - width: UM.Theme.getSize("standard_arrow").width - height: UM.Theme.getSize("standard_arrow").height - color: UM.Theme.getColor("small_button_text") - - sourceSize.height: height - } - } } background: Rectangle From 5bc384830114fb4144709784441f0c5900900bb9 Mon Sep 17 00:00:00 2001 From: Ghostkeeper Date: Fri, 9 Jul 2021 15:33:57 +0200 Subject: [PATCH 18/96] Show either openFileButton or openFileMenu, depending on provider count If there's just 1 provider, show the button. If there are multiple, show the menu. If there are 0, also show the button but disable the button. The behaviour is not yet implemented though. It doesn't actually look at which providers are available and what they do. Contributes to issue CURA-8008. --- plugins/PrepareStage/PrepareMenu.qml | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/plugins/PrepareStage/PrepareMenu.qml b/plugins/PrepareStage/PrepareMenu.qml index 576cd3cd95..219979407b 100644 --- a/plugins/PrepareStage/PrepareMenu.qml +++ b/plugins/PrepareStage/PrepareMenu.qml @@ -13,6 +13,8 @@ Item { id: prepareMenu + property var fileProviderModel: CuraApplication.getFileProviderModel() + UM.I18nCatalog { id: catalog @@ -78,6 +80,8 @@ Item Cura.ExpandablePopup { id: openFileMenu + visible: prepareMenu.fileProviderModel.count > 1 + contentAlignment: Cura.ExpandablePopup.ContentAlignment.AlignLeft headerCornerSide: Cura.RoundedRectangle.Direction.All headerPadding: Math.round((parent.height - UM.Theme.getSize("button_icon").height) / 2) @@ -107,11 +111,12 @@ Item Button { id: openFileButton + visible: prepareMenu.fileProviderModel.count <= 1 height: parent.height - width: height //Square button. + width: visible ? height : 0 //Square button (and don't take up space if invisible). onClicked: Cura.Actions.open.trigger() - enabled: visible + enabled: visible && prepareMenu.fileProviderModel.count > 0 hoverEnabled: true contentItem: Item From 0db1f1034b164b783ff395afc87e7cdc1e13a183 Mon Sep 17 00:00:00 2001 From: Ghostkeeper Date: Fri, 9 Jul 2021 16:47:51 +0200 Subject: [PATCH 19/96] Add header, and make popup grow to its contents It was quite a hassle to allow the column to grow to the size of its contents. For some reason, things update the size to 0. And the size updates again once the pop-up actually gets opened for the first time, because then the column actually gets populated lazily. Contributes to issue CURA-8008. --- plugins/PrepareStage/PrepareMenu.qml | 38 ++++++++++++++++++++++++---- 1 file changed, 33 insertions(+), 5 deletions(-) diff --git a/plugins/PrepareStage/PrepareMenu.qml b/plugins/PrepareStage/PrepareMenu.qml index 219979407b..1916a5813d 100644 --- a/plugins/PrepareStage/PrepareMenu.qml +++ b/plugins/PrepareStage/PrepareMenu.qml @@ -1,7 +1,7 @@ // Copyright (c) 2021 Ultimaker B.V. // Cura is released under the terms of the LGPLv3 or higher. -import QtQuick 2.7 +import QtQuick 2.9 import QtQuick.Layouts 1.1 import QtQuick.Controls 2.3 @@ -99,11 +99,39 @@ Item sourceSize.height: height } - contentItem: Rectangle + contentItem: Item { - width: 100 - height: 100 - color: "red" + id: popup + width: openProviderColumn.width + height: openProviderColumn.height + + Column + { + id: openProviderColumn + + //The column doesn't automatically listen to its children rect if the children change internally, so we need to explicitly update the size. + onChildrenRectChanged: + { + popup.height = childrenRect.height + popup.width = childrenRect.width + } + onPositioningComplete: + { + popup.height = childrenRect.height + popup.width = childrenRect.width + } + + Label + { + text: catalog.i18nc("@menu:header", "Open file") + color: UM.Theme.getColor("text_medium") + font: UM.Theme.getFont("medium") + renderType: Text.NativeRendering + + width: contentWidth + height: contentHeight + } + } } } From f8aa6a3398d2dda18b7c78b6121281f137cd5c6f Mon Sep 17 00:00:00 2001 From: Ghostkeeper Date: Fri, 9 Jul 2021 17:02:38 +0200 Subject: [PATCH 20/96] Add list of open file providers to submenu The layout isn't quite there yet, but it mostly works and I want to have a save point to return to if I tinker too much. Contributes to issue CURA-8008. --- plugins/PrepareStage/PrepareMenu.qml | 43 ++++++++++++++++++++++++++++ 1 file changed, 43 insertions(+) diff --git a/plugins/PrepareStage/PrepareMenu.qml b/plugins/PrepareStage/PrepareMenu.qml index 1916a5813d..31da2f356b 100644 --- a/plugins/PrepareStage/PrepareMenu.qml +++ b/plugins/PrepareStage/PrepareMenu.qml @@ -131,6 +131,49 @@ Item width: contentWidth height: contentHeight } + + Repeater + { + model: prepareMenu.fileProviderModel + delegate: Button + { + leftPadding: UM.Theme.getSize("thick_margin").width + rightPadding: UM.Theme.getSize("thick_margin").width + width: contentItem.width + leftPadding + rightPadding + height: UM.Theme.getSize("action_button").height + hoverEnabled: true + + contentItem: Label + { + text: model.displayText + color: UM.Theme.getColor("text") + font: UM.Theme.getFont("medium") + renderType: Text.NativeRendering + verticalAlignment: Text.AlignVCenter + + width: contentWidth + height: contentHeight + } + + onClicked: + { + if(model.index == 0) //The 0th element is the "From Disk" option, which should activate the open local file dialog. + { + Cura.Actions.open.trigger(); + } + else + { + prepareMenu.fileProviderModel.trigger(model.name); + } + } + + background: Rectangle + { + color: parent.hovered ? UM.Theme.getColor("action_button_hovered") : "transparent" + radius: UM.Theme.getSize("action_button_radius").width + } + } + } } } } From 739f8834d0de2a1a04be14814510bcb2784d8066 Mon Sep 17 00:00:00 2001 From: Ghostkeeper Date: Fri, 9 Jul 2021 17:20:32 +0200 Subject: [PATCH 21/96] Align layout of providers with machine selector It's quite different in detail because there is a lot less content to show here (no machine type, icons, etc), but the basics are the same now. One possible issue is that the button doesn't extend all the way to the right, so you can't click everywhere on the shortest item. I'll see if that can still be fixed. Contributes to issue CURA-8008. --- plugins/PrepareStage/PrepareMenu.qml | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/plugins/PrepareStage/PrepareMenu.qml b/plugins/PrepareStage/PrepareMenu.qml index 31da2f356b..5126d0aba6 100644 --- a/plugins/PrepareStage/PrepareMenu.qml +++ b/plugins/PrepareStage/PrepareMenu.qml @@ -85,6 +85,7 @@ Item contentAlignment: Cura.ExpandablePopup.ContentAlignment.AlignLeft headerCornerSide: Cura.RoundedRectangle.Direction.All headerPadding: Math.round((parent.height - UM.Theme.getSize("button_icon").height) / 2) + contentPadding: UM.Theme.getSize("default_lining").width enabled: visible height: parent.height @@ -102,8 +103,6 @@ Item contentItem: Item { id: popup - width: openProviderColumn.width - height: openProviderColumn.height Column { @@ -127,9 +126,11 @@ Item color: UM.Theme.getColor("text_medium") font: UM.Theme.getFont("medium") renderType: Text.NativeRendering + verticalAlignment: Text.AlignVCenter width: contentWidth - height: contentHeight + height: UM.Theme.getSize("action_button").height + leftPadding: UM.Theme.getSize("default_margin").width } Repeater @@ -152,7 +153,7 @@ Item verticalAlignment: Text.AlignVCenter width: contentWidth - height: contentHeight + height: parent.height } onClicked: @@ -171,6 +172,7 @@ Item { color: parent.hovered ? UM.Theme.getColor("action_button_hovered") : "transparent" radius: UM.Theme.getSize("action_button_radius").width + width: popup.width } } } From c78618bc157a56ace65f6363453139a12d50fa15 Mon Sep 17 00:00:00 2001 From: Remco Burema Date: Fri, 9 Jul 2021 21:06:49 +0200 Subject: [PATCH 22/96] Digital Library: Allow 'personal users' to DL. Users with an account and an UM printer should have some basic access to the Digital Library. To this end, and to remain future proof, the online team has made an extension to its API so now feature budgets can be gauge. At the moment it's only checked wether the user has any access to personal projects at all. If so, the interface shows Digital Library functionality. Known issue: Removing the last printer from DF while still logged in leaves the DL access in the Cura interface until logged out or Cura restarted. Additionally, I think the response for a logged in user without any printer from the API is just 'data = empty list' instead of everything set to False and 0 (which should be the case as they're all listed as required fields in their docs ... maybe I'm missing something). In any case, the code as is now can handle that as well. CURA-8138 --- .../src/DigitalFactoryApiClient.py | 21 +++++++++ .../src/DigitalFactoryController.py | 18 +++++++- .../DigitalFactoryFeatureBudgetResponse.py | 43 +++++++++++++++++++ .../src/DigitalFactoryFileProvider.py | 4 +- .../src/DigitalFactoryOutputDevice.py | 4 +- 5 files changed, 84 insertions(+), 6 deletions(-) create mode 100644 plugins/DigitalLibrary/src/DigitalFactoryFeatureBudgetResponse.py diff --git a/plugins/DigitalLibrary/src/DigitalFactoryApiClient.py b/plugins/DigitalLibrary/src/DigitalFactoryApiClient.py index b0e34adaba..0140d9858d 100644 --- a/plugins/DigitalLibrary/src/DigitalFactoryApiClient.py +++ b/plugins/DigitalLibrary/src/DigitalFactoryApiClient.py @@ -22,6 +22,7 @@ from .DFFileUploader import DFFileUploader from .DFLibraryFileUploadRequest import DFLibraryFileUploadRequest from .DFLibraryFileUploadResponse import DFLibraryFileUploadResponse from .DFPrintJobUploadRequest import DFPrintJobUploadRequest +from .DigitalFactoryFeatureBudgetResponse import DigitalFactoryFeatureBudgetResponse from .DigitalFactoryFileResponse import DigitalFactoryFileResponse from .DigitalFactoryProjectResponse import DigitalFactoryProjectResponse from .PaginationLinks import PaginationLinks @@ -57,6 +58,26 @@ class DigitalFactoryApiClient: self._projects_pagination_mgr = PaginationManager(limit = projects_limit_per_page) if projects_limit_per_page else None # type: Optional[PaginationManager] + def checkUserHasAccess(self, callback: Callable) -> bool: + """Checks if the user has any sort of access to the digital library. + A user is considered to have access if the max-# of private projects is greater then 0 (or -1 for unlimited). + """ + + def callbackWrap(response: Optional[Any] = None, *args, **kwargs) -> None: + if response and isinstance(response, DigitalFactoryFeatureBudgetResponse): + callback( + response.library_max_private_projects == -1 or # Note: -1 is unlimited + response.library_max_private_projects > 0) + else: + Logger.warning(f"Digital Factory: Response is not a feature budget, likely an error: {str(response)}") + callback(False) + + self._http.get(f"{self.CURA_API_ROOT}/feature_budgets", + scope = self._scope, + callback = self._parseCallback(callbackWrap, DigitalFactoryFeatureBudgetResponse, callbackWrap), + error_callback = callbackWrap, + timeout = self.DEFAULT_REQUEST_TIMEOUT) + def getProject(self, library_project_id: str, on_finished: Callable[[DigitalFactoryProjectResponse], Any], failed: Callable) -> None: """ Retrieves a digital factory project by its library project id. diff --git a/plugins/DigitalLibrary/src/DigitalFactoryController.py b/plugins/DigitalLibrary/src/DigitalFactoryController.py index 352a8c70f2..368b29219a 100644 --- a/plugins/DigitalLibrary/src/DigitalFactoryController.py +++ b/plugins/DigitalLibrary/src/DigitalFactoryController.py @@ -89,6 +89,9 @@ class DigitalFactoryController(QObject): uploadFileError = Signal() uploadFileFinished = Signal() + """Signal to inform about the state of user access.""" + userAccessStateChanged = pyqtSignal(bool) + def __init__(self, application: CuraApplication) -> None: super().__init__(parent = None) @@ -106,6 +109,7 @@ class DigitalFactoryController(QObject): self._has_more_projects_to_load = False self._account = self._application.getInstance().getCuraAPI().account # type: Account + self._account.loginStateChanged.connect(self._onLoginStateChanged) self._current_workspace_information = CuraApplication.getInstance().getCurrentWorkspaceInformation() # Initialize the project model @@ -131,6 +135,8 @@ class DigitalFactoryController(QObject): self._application.engineCreatedSignal.connect(self._onEngineCreated) self._application.initializationFinished.connect(self._applicationInitializationFinished) + self._user_has_access = False + def clear(self) -> None: self._project_model.clearProjects() self._api.clear() @@ -143,16 +149,24 @@ class DigitalFactoryController(QObject): self.setSelectedProjectIndex(-1) + def _onLoginStateChanged(self, logged_in: bool) -> None: + def callback(has_access, **kwargs): + self._user_has_access = has_access + self.userAccessStateChanged.emit(logged_in) + + self._api.checkUserHasAccess(callback) + def userAccountHasLibraryAccess(self) -> bool: """ Checks whether the currently logged in user account has access to the Digital Library :return: True if the user account has Digital Library access, else False """ - subscriptions = [] # type: List[Dict[str, Any]] if self._account.userProfile: subscriptions = self._account.userProfile.get("subscriptions", []) - return len(subscriptions) > 0 + if len(subscriptions) > 0: + return True + return self._user_has_access def initialize(self, preselected_project_id: Optional[str] = None) -> None: self.clear() diff --git a/plugins/DigitalLibrary/src/DigitalFactoryFeatureBudgetResponse.py b/plugins/DigitalLibrary/src/DigitalFactoryFeatureBudgetResponse.py new file mode 100644 index 0000000000..016306a478 --- /dev/null +++ b/plugins/DigitalLibrary/src/DigitalFactoryFeatureBudgetResponse.py @@ -0,0 +1,43 @@ +# Copyright (c) 2021 Ultimaker B.V. +# Cura is released under the terms of the LGPLv3 or higher. + +from .BaseModel import BaseModel +from typing import Optional + + +class DigitalFactoryFeatureBudgetResponse(BaseModel): + """Class representing the capabilities of a user account for Digital Library. + NOTE: For each max_..._projects fields, '-1' means unlimited! + """ + + def __init__(self, + library_can_use_business_value: Optional[bool] = False, + library_can_use_comments: Optional[bool] = False, + library_can_use_status: Optional[bool] = False, + library_can_use_tags: Optional[bool] = False, + library_can_use_technical_requirements: Optional[bool] = False, + library_max_organization_shared_projects: Optional[int] = False, # -1 means unlimited + library_max_private_projects: Optional[int] = False, # -1 means unlimited + library_max_team_shared_projects: Optional[int] = False, # -1 means unlimited + **kwargs) -> None: + + self.library_can_use_business_value = library_can_use_business_value + self.library_can_use_comments = library_can_use_comments + self.library_can_use_status = library_can_use_status + self.library_can_use_tags = library_can_use_tags + self.library_can_use_technical_requirements = library_can_use_technical_requirements + self.library_max_organization_shared_projects = library_max_organization_shared_projects # -1 means unlimited + self.library_max_private_projects = library_max_private_projects # -1 means unlimited + self.library_max_team_shared_projects = library_max_team_shared_projects # -1 means unlimited + super().__init__(**kwargs) + + def __repr__(self) -> str: + return "max private: {}, max org: {}, max team: {}".format( + self.library_max_private_projects, + self.library_max_organization_shared_projects, + self.library_max_team_shared_projects) + + # Validates the model, raising an exception if the model is invalid. + def validate(self) -> None: + super().validate() + # No validation for now, as the response can be "data: []", which should be interpreted as all False and 0's diff --git a/plugins/DigitalLibrary/src/DigitalFactoryFileProvider.py b/plugins/DigitalLibrary/src/DigitalFactoryFileProvider.py index 7a544afaa1..65a727e21a 100644 --- a/plugins/DigitalLibrary/src/DigitalFactoryFileProvider.py +++ b/plugins/DigitalLibrary/src/DigitalFactoryFileProvider.py @@ -22,7 +22,7 @@ class DigitalFactoryFileProvider(FileProvider): self._dialog = None self._account = CuraApplication.getInstance().getCuraAPI().account # type: Account - self._account.loginStateChanged.connect(self._onLoginStateChanged) + self._controller.userAccessStateChanged.connect(self._onUserAccessStateChanged) self.enabled = self._account.isLoggedIn and self._controller.userAccountHasLibraryAccess() self.priority = 10 @@ -53,7 +53,7 @@ class DigitalFactoryFileProvider(FileProvider): if not self._dialog: Logger.log("e", "Unable to create the Digital Library Open dialog.") - def _onLoginStateChanged(self, logged_in: bool) -> None: + def _onUserAccessStateChanged(self, logged_in: bool) -> None: """ Sets the enabled status of the DigitalFactoryFileProvider according to the account's login status :param logged_in: The new login status diff --git a/plugins/DigitalLibrary/src/DigitalFactoryOutputDevice.py b/plugins/DigitalLibrary/src/DigitalFactoryOutputDevice.py index 202223f9b4..70e3ac34f2 100644 --- a/plugins/DigitalLibrary/src/DigitalFactoryOutputDevice.py +++ b/plugins/DigitalLibrary/src/DigitalFactoryOutputDevice.py @@ -45,7 +45,7 @@ class DigitalFactoryOutputDevice(ProjectOutputDevice): self._writing = False self._account = CuraApplication.getInstance().getCuraAPI().account # type: Account - self._account.loginStateChanged.connect(self._onLoginStateChanged) + self._controller.userAccessStateChanged.connect(self._onUserAccessStateChanged) self.enabled = self._account.isLoggedIn and self._controller.userAccountHasLibraryAccess() self._current_workspace_information = CuraApplication.getInstance().getCurrentWorkspaceInformation() @@ -97,7 +97,7 @@ class DigitalFactoryOutputDevice(ProjectOutputDevice): if not self._dialog: Logger.log("e", "Unable to create the Digital Library Save dialog.") - def _onLoginStateChanged(self, logged_in: bool) -> None: + def _onUserAccessStateChanged(self, logged_in: bool) -> None: """ Sets the enabled status of the DigitalFactoryOutputDevice according to the account's login status :param logged_in: The new login status From 6f99837db575648ffee21715acefd218d7046de0 Mon Sep 17 00:00:00 2001 From: Remco Burema Date: Fri, 9 Jul 2021 21:17:33 +0200 Subject: [PATCH 23/96] Fix typing. part of CURA-8138 --- plugins/DigitalLibrary/src/DigitalFactoryApiClient.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/plugins/DigitalLibrary/src/DigitalFactoryApiClient.py b/plugins/DigitalLibrary/src/DigitalFactoryApiClient.py index 0140d9858d..3560182aa0 100644 --- a/plugins/DigitalLibrary/src/DigitalFactoryApiClient.py +++ b/plugins/DigitalLibrary/src/DigitalFactoryApiClient.py @@ -58,7 +58,7 @@ class DigitalFactoryApiClient: self._projects_pagination_mgr = PaginationManager(limit = projects_limit_per_page) if projects_limit_per_page else None # type: Optional[PaginationManager] - def checkUserHasAccess(self, callback: Callable) -> bool: + def checkUserHasAccess(self, callback: Callable) -> None: """Checks if the user has any sort of access to the digital library. A user is considered to have access if the max-# of private projects is greater then 0 (or -1 for unlimited). """ @@ -66,6 +66,7 @@ class DigitalFactoryApiClient: def callbackWrap(response: Optional[Any] = None, *args, **kwargs) -> None: if response and isinstance(response, DigitalFactoryFeatureBudgetResponse): callback( + response.library_max_private_projects is not None and response.library_max_private_projects == -1 or # Note: -1 is unlimited response.library_max_private_projects > 0) else: From 85f98bdaffe671f66049baffec82188b008f8426 Mon Sep 17 00:00:00 2001 From: Remco Burema Date: Fri, 9 Jul 2021 21:36:20 +0200 Subject: [PATCH 24/96] Appease type-checking system even further. That last one should have worked really. part of CURA-8138 --- plugins/DigitalLibrary/src/DigitalFactoryApiClient.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/plugins/DigitalLibrary/src/DigitalFactoryApiClient.py b/plugins/DigitalLibrary/src/DigitalFactoryApiClient.py index 3560182aa0..e1a62fdd5c 100644 --- a/plugins/DigitalLibrary/src/DigitalFactoryApiClient.py +++ b/plugins/DigitalLibrary/src/DigitalFactoryApiClient.py @@ -64,9 +64,9 @@ class DigitalFactoryApiClient: """ def callbackWrap(response: Optional[Any] = None, *args, **kwargs) -> None: - if response and isinstance(response, DigitalFactoryFeatureBudgetResponse): + if (response is not None and isinstance(response, DigitalFactoryFeatureBudgetResponse) and + response.library_max_private_projects is not None): callback( - response.library_max_private_projects is not None and response.library_max_private_projects == -1 or # Note: -1 is unlimited response.library_max_private_projects > 0) else: From a1387f7ed7d8ee2ee76ad626edab7f21ca6f07d6 Mon Sep 17 00:00:00 2001 From: Dave Date: Sat, 10 Jul 2021 18:24:00 +0200 Subject: [PATCH 25/96] Update geeetech_a30.def.json wrong name for the settings --- resources/definitions/geeetech_a30.def.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/resources/definitions/geeetech_a30.def.json b/resources/definitions/geeetech_a30.def.json index 1f08d37445..d4f7df139f 100644 --- a/resources/definitions/geeetech_a30.def.json +++ b/resources/definitions/geeetech_a30.def.json @@ -4,7 +4,7 @@ "inherits": "fdmprinter", "metadata": { "author": "William & Cataldo URSO", - "manufacturer": "Shenzhen Geeetech Technology", + "manufacturer": "Geeetech", "file_formats": "text/x-gcode", "visible": true, "has_materials": true, From 55bdb81e785bf9fa94e419076cca58b55a74334a Mon Sep 17 00:00:00 2001 From: Ghostkeeper Date: Mon, 12 Jul 2021 11:13:06 +0200 Subject: [PATCH 26/96] Reduce margins of options in the open file drop-down This was a desire from the developer. It shouldn't be consistent with the printer selector. The margins being all the same is more important. Contributes to issue CURA-8008. --- plugins/PrepareStage/PrepareMenu.qml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/plugins/PrepareStage/PrepareMenu.qml b/plugins/PrepareStage/PrepareMenu.qml index 5126d0aba6..061db0b8f6 100644 --- a/plugins/PrepareStage/PrepareMenu.qml +++ b/plugins/PrepareStage/PrepareMenu.qml @@ -138,8 +138,8 @@ Item model: prepareMenu.fileProviderModel delegate: Button { - leftPadding: UM.Theme.getSize("thick_margin").width - rightPadding: UM.Theme.getSize("thick_margin").width + leftPadding: UM.Theme.getSize("default_margin").width + rightPadding: UM.Theme.getSize("default_margin").width width: contentItem.width + leftPadding + rightPadding height: UM.Theme.getSize("action_button").height hoverEnabled: true From 3d6b58d5c08a1f3b8901b47d33bbb13d780926b7 Mon Sep 17 00:00:00 2001 From: Ghostkeeper Date: Mon, 12 Jul 2021 11:19:04 +0200 Subject: [PATCH 27/96] Always show down arrow regardless of expanded state This is something our UX designer wants to change for all expandable header bar menus. The down arrow indicates that something will pop-up downwards once clicked. It is unnecessary to feedback the state of the expansion in the icon. Contributes to CURA-8008. --- resources/qml/ExpandableComponent.qml | 2 +- resources/qml/ExpandablePopup.qml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/resources/qml/ExpandableComponent.qml b/resources/qml/ExpandableComponent.qml index bbe617e27d..18eb8c0fa6 100644 --- a/resources/qml/ExpandableComponent.qml +++ b/resources/qml/ExpandableComponent.qml @@ -167,7 +167,7 @@ Item verticalCenter: parent.verticalCenter margins: background.padding } - source: expanded ? UM.Theme.getIcon("ChevronSingleDown") : UM.Theme.getIcon("ChevronSingleLeft") + source: UM.Theme.getIcon("ChevronSingleDown") visible: source != "" width: UM.Theme.getSize("standard_arrow").width height: UM.Theme.getSize("standard_arrow").height diff --git a/resources/qml/ExpandablePopup.qml b/resources/qml/ExpandablePopup.qml index da56470bfb..3bcfdbb6f8 100644 --- a/resources/qml/ExpandablePopup.qml +++ b/resources/qml/ExpandablePopup.qml @@ -180,7 +180,7 @@ Item verticalCenter: parent.verticalCenter margins: background.padding } - source: expanded ? UM.Theme.getIcon("ChevronSingleDown") : UM.Theme.getIcon("ChevronSingleLeft") + source: UM.Theme.getIcon("ChevronSingleDown") visible: source != "" width: UM.Theme.getSize("standard_arrow").width height: UM.Theme.getSize("standard_arrow").height From 9ec261f72169bf87d7add73ad09d304067bed3f9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lars=20P=C3=B6pperl?= <45465820+tispokes@users.noreply.github.com> Date: Mon, 12 Jul 2021 13:08:42 +0200 Subject: [PATCH 28/96] =?UTF-8?q?corrected=20z=5Fseam-"Back"=20from=20"Zur?= =?UTF-8?q?=C3=BCck"=20to=20"Hinten"?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- resources/i18n/de_DE/fdmprinter.def.json.po | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/resources/i18n/de_DE/fdmprinter.def.json.po b/resources/i18n/de_DE/fdmprinter.def.json.po index 5d7915ac0d..3eb590b680 100644 --- a/resources/i18n/de_DE/fdmprinter.def.json.po +++ b/resources/i18n/de_DE/fdmprinter.def.json.po @@ -1177,7 +1177,7 @@ msgstr "Hinten links" #: fdmprinter.def.json msgctxt "z_seam_position option back" msgid "Back" -msgstr "Zurück" +msgstr "Hinten" #: fdmprinter.def.json msgctxt "z_seam_position option backright" From 2b5747f3eefb673734b366250a6dc671acc25760 Mon Sep 17 00:00:00 2001 From: Jaime van Kessel Date: Mon, 12 Jul 2021 17:13:32 +0200 Subject: [PATCH 29/96] Update plugins/UM3NetworkPrinting/src/Cloud/CloudOutputDevice.py Co-authored-by: Ghostkeeper --- plugins/UM3NetworkPrinting/src/Cloud/CloudOutputDevice.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/UM3NetworkPrinting/src/Cloud/CloudOutputDevice.py b/plugins/UM3NetworkPrinting/src/Cloud/CloudOutputDevice.py index 9a996444a6..3ca150ec87 100644 --- a/plugins/UM3NetworkPrinting/src/Cloud/CloudOutputDevice.py +++ b/plugins/UM3NetworkPrinting/src/Cloud/CloudOutputDevice.py @@ -260,7 +260,7 @@ class CloudOutputDevice(UltimakerNetworkedPrinterOutputDevice): message.addAction("monitor print", name=I18N_CATALOG.i18nc("@action:button", "Monitor Print"), icon="", - description="Remove the plugin", + description=I18N_CATALOG.i18nc("@action:tooltip", "Track the print in Ultimaker Digital Factory"), button_align=message.ActionButtonAlignment.ALIGN_RIGHT) df_url = "https://digitalfactory.ultimaker.com/app/jobs/%s?utm_source=cura&utm_medium=software&utm_campaign=monitor-button" % self._cluster.cluster_id message.pyQtActionTriggered.connect(lambda message, action: (QDesktopServices.openUrl(QUrl(df_url)), message.hide())) From 22826bc4d89a425812b2d003edeb273c8a10cdab Mon Sep 17 00:00:00 2001 From: Ghostkeeper Date: Mon, 12 Jul 2021 17:16:16 +0200 Subject: [PATCH 30/96] Add text field in a layout for search The text field is not stylised yet, so far. Will do, but let's first make it functional. Contributes to issue CURA-8009. --- .../resources/qml/SelectProjectPage.qml | 52 +++++++++++-------- 1 file changed, 30 insertions(+), 22 deletions(-) diff --git a/plugins/DigitalLibrary/resources/qml/SelectProjectPage.qml b/plugins/DigitalLibrary/resources/qml/SelectProjectPage.qml index 2de0e78cc7..4fcccac61e 100644 --- a/plugins/DigitalLibrary/resources/qml/SelectProjectPage.qml +++ b/plugins/DigitalLibrary/resources/qml/SelectProjectPage.qml @@ -1,10 +1,12 @@ // Copyright (C) 2021 Ultimaker B.V. +// Cura is released under the terms of the LGPLv3 or higher. import QtQuick 2.10 import QtQuick.Window 2.2 import QtQuick.Controls 1.4 as OldControls // TableView doesn't exist in the QtQuick Controls 2.x in 5.10, so use the old one import QtQuick.Controls 2.3 import QtQuick.Controls.Styles 1.4 +import QtQuick.Layouts 1.1 import UM 1.2 as UM import Cura 1.6 as Cura @@ -29,31 +31,37 @@ Item margins: UM.Theme.getSize("default_margin").width } - Label + RowLayout { - id: selectProjectLabel + id: headerRow - text: "Select Project" - font: UM.Theme.getFont("medium") - color: UM.Theme.getColor("small_button_text") - anchors.top: parent.top - anchors.left: parent.left - visible: projectListContainer.visible - } - - Cura.SecondaryButton - { - id: createNewProjectButton - - anchors.verticalCenter: selectProjectLabel.verticalCenter - anchors.right: parent.right - text: "New Library project" - - onClicked: + anchors { - createNewProjectPopup.open() + top: parent.top + left: parent.left + right: parent.right + } + height: childrenRect.height + + TextField + { + id: searchBar + Layout.fillWidth: true + height: createNewProjectButton.height + } + + Cura.SecondaryButton + { + id: createNewProjectButton + + text: "New Library project" + + onClicked: + { + createNewProjectPopup.open() + } + busy: manager.creatingNewProjectStatus == DF.RetrievalStatus.InProgress } - busy: manager.creatingNewProjectStatus == DF.RetrievalStatus.InProgress } Item @@ -106,7 +114,7 @@ Item id: projectListContainer anchors { - top: selectProjectLabel.bottom + top: headerRow.bottom topMargin: UM.Theme.getSize("default_margin").height bottom: parent.bottom left: parent.left From 65f7eb5ea8f0cd5a8c1c7e56e08f1c08fcfc71f4 Mon Sep 17 00:00:00 2001 From: Ghostkeeper Date: Mon, 12 Jul 2021 17:41:10 +0200 Subject: [PATCH 31/96] Add function to update search filter when the user types Seems to work fine. The pyqtSignal is not technically necessary unless we display this filter in the interface anywhere. We don't currently. If the signal is not present it would complain about non-notifyable properties. And making it a slot instead of a signal seems a bit unintuitive to me in how the field is being used. Contributes to issue CURA-8009. --- .../resources/qml/SelectProjectPage.qml | 2 + .../src/DigitalFactoryController.py | 39 ++++++++++++++++++- 2 files changed, 40 insertions(+), 1 deletion(-) diff --git a/plugins/DigitalLibrary/resources/qml/SelectProjectPage.qml b/plugins/DigitalLibrary/resources/qml/SelectProjectPage.qml index 4fcccac61e..ecec9556c9 100644 --- a/plugins/DigitalLibrary/resources/qml/SelectProjectPage.qml +++ b/plugins/DigitalLibrary/resources/qml/SelectProjectPage.qml @@ -48,6 +48,8 @@ Item id: searchBar Layout.fillWidth: true height: createNewProjectButton.height + + onTextEdited: manager.projectFilter = text } Cura.SecondaryButton diff --git a/plugins/DigitalLibrary/src/DigitalFactoryController.py b/plugins/DigitalLibrary/src/DigitalFactoryController.py index 368b29219a..3d1cc178f8 100644 --- a/plugins/DigitalLibrary/src/DigitalFactoryController.py +++ b/plugins/DigitalLibrary/src/DigitalFactoryController.py @@ -1,4 +1,6 @@ # Copyright (c) 2021 Ultimaker B.V. +# Cura is released under the terms of the LGPLv3 or higher. + import json import math import os @@ -8,7 +10,7 @@ from enum import IntEnum from pathlib import Path from typing import Optional, List, Dict, Any, cast -from PyQt5.QtCore import pyqtSignal, QObject, pyqtSlot, pyqtProperty, Q_ENUMS, QUrl +from PyQt5.QtCore import pyqtSignal, QObject, pyqtSlot, pyqtProperty, Q_ENUMS, QTimer, QUrl from PyQt5.QtNetwork import QNetworkReply from PyQt5.QtQml import qmlRegisterType, qmlRegisterUncreatableType @@ -116,6 +118,11 @@ class DigitalFactoryController(QObject): self._project_model = DigitalFactoryProjectModel() self._selected_project_idx = -1 self._project_creation_error_text = "Something went wrong while creating a new project. Please try again." + self._project_filter = "" + self._project_filter_change_timer = QTimer() + self._project_filter_change_timer.setInterval(1000) + self._project_filter_change_timer.setSingleShot(True) + self._project_filter_change_timer.timeout.connect(self._applyProjectFilter) # Initialize the file model self._file_model = DigitalFactoryFileModel() @@ -302,6 +309,36 @@ class DigitalFactoryController(QObject): self._selected_file_indices = file_indices self.selectedFileIndicesChanged.emit(file_indices) + def setProjectFilter(self, new_filter) -> None: + """ + Called when the user wants to change the search filter for projects. + + The filter is not immediately applied. There is some delay to allow the user to finish typing. + :param new_filter: The new filter that the user wants to apply. + """ + self._project_filter = new_filter + self._project_filter_change_timer.start() + + """ + Signal to notify Qt that the applied filter has changed. + """ + projectFilterChanged = pyqtSignal() + + @pyqtProperty(str, notify = projectFilterChanged, fset = setProjectFilter) + def projectFilter(self) -> str: + """ + The current search filter being applied to the project list. + :return: The current search filter being applied to the project list. + """ + return self._project_filter + + def _applyProjectFilter(self): + """ + Actually apply the current filter to search for projects with the user-defined search string. + :return: + """ + self.projectFilterChanged.emit() + @pyqtProperty(QObject, constant = True) def digitalFactoryProjectModel(self) -> "DigitalFactoryProjectModel": return self._project_model From 02932a1f62dd62f17d405666ae932d0dec78537a Mon Sep 17 00:00:00 2001 From: Ghostkeeper Date: Mon, 12 Jul 2021 18:43:02 +0200 Subject: [PATCH 32/96] Add filter to API call for project list This passes the filter on to the API call and causes the API call, so that we only get the projects that the user searched for. Contributes to issue CURA-8009. --- plugins/DigitalLibrary/src/DigitalFactoryApiClient.py | 11 ++++++++--- .../DigitalLibrary/src/DigitalFactoryController.py | 3 ++- 2 files changed, 10 insertions(+), 4 deletions(-) diff --git a/plugins/DigitalLibrary/src/DigitalFactoryApiClient.py b/plugins/DigitalLibrary/src/DigitalFactoryApiClient.py index e1a62fdd5c..4ebb3cb051 100644 --- a/plugins/DigitalLibrary/src/DigitalFactoryApiClient.py +++ b/plugins/DigitalLibrary/src/DigitalFactoryApiClient.py @@ -95,7 +95,7 @@ class DigitalFactoryApiClient: error_callback = failed, timeout = self.DEFAULT_REQUEST_TIMEOUT) - def getProjectsFirstPage(self, on_finished: Callable[[List[DigitalFactoryProjectResponse]], Any], failed: Callable) -> None: + def getProjectsFirstPage(self, search_filter: str, on_finished: Callable[[List[DigitalFactoryProjectResponse]], Any], failed: Callable) -> None: """ Retrieves digital factory projects for the user that is currently logged in. @@ -103,13 +103,18 @@ class DigitalFactoryApiClient: according to the limit set in the pagination manager. If there is no projects pagination manager, this function leaves the project limit to the default set on the server side (999999). + :param search_filter: Text to filter the search results. If given an empty string, results are not filtered. :param on_finished: The function to be called after the result is parsed. :param failed: The function to be called if the request fails. """ - url = "{}/projects".format(self.CURA_API_ROOT) + url = f"{self.CURA_API_ROOT}/projects" + query_character = "?" if self._projects_pagination_mgr: self._projects_pagination_mgr.reset() # reset to clear all the links and response metadata - url += "?limit={}".format(self._projects_pagination_mgr.limit) + url += f"{query_character}limit={self._projects_pagination_mgr.limit}" + query_character = "&" + if search_filter != "": + url += f"{query_character}search={search_filter}" self._http.get(url, scope = self._scope, diff --git a/plugins/DigitalLibrary/src/DigitalFactoryController.py b/plugins/DigitalLibrary/src/DigitalFactoryController.py index 3d1cc178f8..a5cc2936a3 100644 --- a/plugins/DigitalLibrary/src/DigitalFactoryController.py +++ b/plugins/DigitalLibrary/src/DigitalFactoryController.py @@ -183,7 +183,7 @@ class DigitalFactoryController(QObject): if preselected_project_id: self._api.getProject(preselected_project_id, on_finished = self.setProjectAsPreselected, failed = self._onGetProjectFailed) else: - self._api.getProjectsFirstPage(on_finished = self._onGetProjectsFirstPageFinished, failed = self._onGetProjectsFailed) + self._api.getProjectsFirstPage(search_filter = self._project_filter, on_finished = self._onGetProjectsFirstPageFinished, failed = self._onGetProjectsFailed) def setProjectAsPreselected(self, df_project: DigitalFactoryProjectResponse) -> None: """ @@ -338,6 +338,7 @@ class DigitalFactoryController(QObject): :return: """ self.projectFilterChanged.emit() + self._api.getProjectsFirstPage(search_filter = self._project_filter, on_finished = self._onGetProjectsFirstPageFinished, failed = self._onGetProjectsFailed) @pyqtProperty(QObject, constant = True) def digitalFactoryProjectModel(self) -> "DigitalFactoryProjectModel": From 94e229aa446a291370bcfa06690907d8233a1793 Mon Sep 17 00:00:00 2001 From: Ghostkeeper Date: Mon, 12 Jul 2021 18:44:11 +0200 Subject: [PATCH 33/96] Clear list of projects every time we load the first page Otherwise when we refresh the project list after searching it would put the new results at the end. That's not what we want. Contributes to issue CURA-8009. --- plugins/DigitalLibrary/src/DigitalFactoryController.py | 1 + 1 file changed, 1 insertion(+) diff --git a/plugins/DigitalLibrary/src/DigitalFactoryController.py b/plugins/DigitalLibrary/src/DigitalFactoryController.py index a5cc2936a3..80f4d37f66 100644 --- a/plugins/DigitalLibrary/src/DigitalFactoryController.py +++ b/plugins/DigitalLibrary/src/DigitalFactoryController.py @@ -211,6 +211,7 @@ class DigitalFactoryController(QObject): :param df_projects: A list of all the Digital Factory Library projects linked to the user's account """ + self.clear() self.setHasMoreProjectsToLoad(self._api.hasMoreProjectsToLoad()) self._project_model.setProjects(df_projects) self.setRetrievingProjectsStatus(RetrievalStatus.Success) From 1269c28d0a14d53a1a2630666b5f9ac8b9241020 Mon Sep 17 00:00:00 2001 From: Ghostkeeper Date: Mon, 12 Jul 2021 18:46:54 +0200 Subject: [PATCH 34/96] Reduce wait time before sending query Most people should be able to type 5 characters per second. And those that can't will just have to see it refresh after every stroke. Contributes to issue CURA-8009. --- plugins/DigitalLibrary/src/DigitalFactoryController.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/DigitalLibrary/src/DigitalFactoryController.py b/plugins/DigitalLibrary/src/DigitalFactoryController.py index 80f4d37f66..796937a9d9 100644 --- a/plugins/DigitalLibrary/src/DigitalFactoryController.py +++ b/plugins/DigitalLibrary/src/DigitalFactoryController.py @@ -120,7 +120,7 @@ class DigitalFactoryController(QObject): self._project_creation_error_text = "Something went wrong while creating a new project. Please try again." self._project_filter = "" self._project_filter_change_timer = QTimer() - self._project_filter_change_timer.setInterval(1000) + self._project_filter_change_timer.setInterval(200) self._project_filter_change_timer.setSingleShot(True) self._project_filter_change_timer.timeout.connect(self._applyProjectFilter) From e8fc88e6b02f465faaa59c7475d0bf59215e804b Mon Sep 17 00:00:00 2001 From: Jaime van Kessel Date: Tue, 13 Jul 2021 09:45:00 +0200 Subject: [PATCH 35/96] Use f-string formatting instead of % CURA-8018 Co-authored-by: Konstantinos Karmas --- plugins/UM3NetworkPrinting/src/Cloud/CloudOutputDevice.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/UM3NetworkPrinting/src/Cloud/CloudOutputDevice.py b/plugins/UM3NetworkPrinting/src/Cloud/CloudOutputDevice.py index 3ca150ec87..86927a43d4 100644 --- a/plugins/UM3NetworkPrinting/src/Cloud/CloudOutputDevice.py +++ b/plugins/UM3NetworkPrinting/src/Cloud/CloudOutputDevice.py @@ -262,7 +262,7 @@ class CloudOutputDevice(UltimakerNetworkedPrinterOutputDevice): icon="", description=I18N_CATALOG.i18nc("@action:tooltip", "Track the print in Ultimaker Digital Factory"), button_align=message.ActionButtonAlignment.ALIGN_RIGHT) - df_url = "https://digitalfactory.ultimaker.com/app/jobs/%s?utm_source=cura&utm_medium=software&utm_campaign=monitor-button" % self._cluster.cluster_id + df_url = f"https://digitalfactory.ultimaker.com/app/jobs/{self._cluster.cluster_id}?utm_source=cura&utm_medium=software&utm_campaign=monitor-button" message.pyQtActionTriggered.connect(lambda message, action: (QDesktopServices.openUrl(QUrl(df_url)), message.hide())) message.show() From e31ec31f344d82f5ca8471f4d618c3276a49ef26 Mon Sep 17 00:00:00 2001 From: Konstantinos Karmas Date: Tue, 13 Jul 2021 09:59:05 +0200 Subject: [PATCH 36/96] Make the lifetime of the "print job sent" message 30s Previously it was 5s and the message would disappear before the user had a chance to press the "Monitor print" button. CURA-8018 --- .../src/Messages/PrintJobUploadSuccessMessage.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/plugins/UM3NetworkPrinting/src/Messages/PrintJobUploadSuccessMessage.py b/plugins/UM3NetworkPrinting/src/Messages/PrintJobUploadSuccessMessage.py index aa64f338dd..aa3d72ccd8 100644 --- a/plugins/UM3NetworkPrinting/src/Messages/PrintJobUploadSuccessMessage.py +++ b/plugins/UM3NetworkPrinting/src/Messages/PrintJobUploadSuccessMessage.py @@ -13,6 +13,5 @@ class PrintJobUploadSuccessMessage(Message): def __init__(self) -> None: super().__init__( text = I18N_CATALOG.i18nc("@info:status", "Print job was successfully sent to the printer."), - title = I18N_CATALOG.i18nc("@info:title", "Data Sent"), - lifetime = 5 + title = I18N_CATALOG.i18nc("@info:title", "Data Sent") ) From 329973adfbea675edd851548b7a6952bcbc42a73 Mon Sep 17 00:00:00 2001 From: Konstantinos Karmas Date: Tue, 13 Jul 2021 10:00:27 +0200 Subject: [PATCH 37/96] Capitalize only the first word in the message action CURA-8018 --- plugins/UM3NetworkPrinting/src/Cloud/CloudOutputDevice.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/UM3NetworkPrinting/src/Cloud/CloudOutputDevice.py b/plugins/UM3NetworkPrinting/src/Cloud/CloudOutputDevice.py index 86927a43d4..9eaa133ef5 100644 --- a/plugins/UM3NetworkPrinting/src/Cloud/CloudOutputDevice.py +++ b/plugins/UM3NetworkPrinting/src/Cloud/CloudOutputDevice.py @@ -258,7 +258,7 @@ class CloudOutputDevice(UltimakerNetworkedPrinterOutputDevice): self._progress.hide() message = PrintJobUploadSuccessMessage() message.addAction("monitor print", - name=I18N_CATALOG.i18nc("@action:button", "Monitor Print"), + name=I18N_CATALOG.i18nc("@action:button", "Monitor print"), icon="", description=I18N_CATALOG.i18nc("@action:tooltip", "Track the print in Ultimaker Digital Factory"), button_align=message.ActionButtonAlignment.ALIGN_RIGHT) From 13ca30ed98c9ab2c2155d2d60465a58dbda92137 Mon Sep 17 00:00:00 2001 From: Ghostkeeper Date: Tue, 13 Jul 2021 14:40:04 +0200 Subject: [PATCH 38/96] Stylise search bar This is the standard style for text fields in Cura. The spacing around the search icon is customised with the best approximation I could get using a simple string of placeholderText. Contributes to issue CURA-8009. --- .../resources/qml/SelectProjectPage.qml | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/plugins/DigitalLibrary/resources/qml/SelectProjectPage.qml b/plugins/DigitalLibrary/resources/qml/SelectProjectPage.qml index ecec9556c9..08bf8aec7c 100644 --- a/plugins/DigitalLibrary/resources/qml/SelectProjectPage.qml +++ b/plugins/DigitalLibrary/resources/qml/SelectProjectPage.qml @@ -43,13 +43,20 @@ Item } height: childrenRect.height - TextField + Cura.TextField { id: searchBar Layout.fillWidth: true height: createNewProjectButton.height - onTextEdited: manager.projectFilter = text + onTextEdited: manager.projectFilter = text //Update the search filter when editing this text field. + + placeholderText: + { + var image_size = "width=\"" + UM.Theme.getSize("small_button_icon").width + "\" height=\"" + UM.Theme.getSize("small_button_icon").height + "\" "; + var image_source = "src=\"" + UM.Theme.getIcon("Magnifier") + "\""; + return "   Search"; + } } Cura.SecondaryButton From 1566a282dcad5f5405f4e3d5ac6ecdd431513007 Mon Sep 17 00:00:00 2001 From: Ghostkeeper Date: Tue, 13 Jul 2021 15:16:09 +0200 Subject: [PATCH 39/96] Replace text and image if there's no projects due to search It's a bit weird if it shows that you didn't add any projects yet if you just type in a gibberish search keyword. Contributes to issue CURA-8009. --- .../resources/images/projects_not_found.svg | 62 +++++++++++++++++++ .../resources/qml/SelectProjectPage.qml | 5 +- 2 files changed, 65 insertions(+), 2 deletions(-) create mode 100644 plugins/DigitalLibrary/resources/images/projects_not_found.svg diff --git a/plugins/DigitalLibrary/resources/images/projects_not_found.svg b/plugins/DigitalLibrary/resources/images/projects_not_found.svg new file mode 100644 index 0000000000..8aee7b797c --- /dev/null +++ b/plugins/DigitalLibrary/resources/images/projects_not_found.svg @@ -0,0 +1,62 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/plugins/DigitalLibrary/resources/qml/SelectProjectPage.qml b/plugins/DigitalLibrary/resources/qml/SelectProjectPage.qml index 08bf8aec7c..3f1799b9ae 100644 --- a/plugins/DigitalLibrary/resources/qml/SelectProjectPage.qml +++ b/plugins/DigitalLibrary/resources/qml/SelectProjectPage.qml @@ -93,7 +93,7 @@ Item { id: digitalFactoryImage anchors.horizontalCenter: parent.horizontalCenter - source: "../images/digital_factory.svg" + source: searchBar.text === "" ? "../images/digital_factory.svg" : "../images/projects_not_found.svg" fillMode: Image.PreserveAspectFit width: parent.width - 2 * UM.Theme.getSize("thick_margin").width sourceSize.width: width @@ -104,7 +104,7 @@ Item { id: noLibraryProjectsLabel anchors.horizontalCenter: parent.horizontalCenter - text: "It appears that you don't have any projects in the Library yet." + text: searchBar.text === "" ? "It appears that you don't have any projects in the Library yet." : "No projects found that match the search query." font: UM.Theme.getFont("medium") } @@ -114,6 +114,7 @@ Item anchors.horizontalCenter: parent.horizontalCenter text: "Visit Digital Library" onClicked: Qt.openUrlExternally(CuraApplication.ultimakerDigitalFactoryUrl + "/app/library") + visible: searchBar.text === "" //Show the link to Digital Library when there are no projects in the user's Library. } } } From d4f249277ecfc51630c017fda0d43744f513c195 Mon Sep 17 00:00:00 2001 From: Jaime van Kessel Date: Tue, 13 Jul 2021 15:20:41 +0200 Subject: [PATCH 40/96] Change icon in simulation view to rectangle CURA-8379 --- plugins/SimulationView/SimulationViewMenuComponent.qml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/plugins/SimulationView/SimulationViewMenuComponent.qml b/plugins/SimulationView/SimulationViewMenuComponent.qml index 86e686e0fc..6dde44c8ae 100644 --- a/plugins/SimulationView/SimulationViewMenuComponent.qml +++ b/plugins/SimulationView/SimulationViewMenuComponent.qml @@ -203,16 +203,16 @@ Cura.ExpandableComponent style: UM.Theme.styles.checkbox - - UM.RecolorImage + Rectangle { id: swatch anchors.verticalCenter: parent.verticalCenter anchors.right: extrudersModelCheckBox.right width: UM.Theme.getSize("layerview_legend_size").width height: UM.Theme.getSize("layerview_legend_size").height - source: UM.Theme.getIcon("Extruder", "medium") color: model.color + border.width: UM.Theme.getSize("default_lining").width + border.color: UM.Theme.getColor("lining") } Label From bec83920e46d3f5f82ded82a8c26b4a4fb5b3a4d Mon Sep 17 00:00:00 2001 From: Ghostkeeper Date: Tue, 13 Jul 2021 15:47:21 +0200 Subject: [PATCH 41/96] Keep showing search icon while typing search query This adds an option to the TextField element to show an icon on the left side in the text field. The icon remains visible when the user types in something (it's not part of the placeholder string). Then we use that optional icon for the search bar in the Digital Library. Contributes to issue CURA-8009. --- .../resources/qml/SelectProjectPage.qml | 9 +++----- resources/qml/Widgets/TextField.qml | 21 +++++++++++++++++++ 2 files changed, 24 insertions(+), 6 deletions(-) diff --git a/plugins/DigitalLibrary/resources/qml/SelectProjectPage.qml b/plugins/DigitalLibrary/resources/qml/SelectProjectPage.qml index 3f1799b9ae..36e3de3da7 100644 --- a/plugins/DigitalLibrary/resources/qml/SelectProjectPage.qml +++ b/plugins/DigitalLibrary/resources/qml/SelectProjectPage.qml @@ -51,12 +51,8 @@ Item onTextEdited: manager.projectFilter = text //Update the search filter when editing this text field. - placeholderText: - { - var image_size = "width=\"" + UM.Theme.getSize("small_button_icon").width + "\" height=\"" + UM.Theme.getSize("small_button_icon").height + "\" "; - var image_source = "src=\"" + UM.Theme.getIcon("Magnifier") + "\""; - return "   Search"; - } + leftIcon: UM.Theme.getIcon("Magnifier") + placeholderText: "Search" } Cura.SecondaryButton @@ -106,6 +102,7 @@ Item anchors.horizontalCenter: parent.horizontalCenter text: searchBar.text === "" ? "It appears that you don't have any projects in the Library yet." : "No projects found that match the search query." font: UM.Theme.getFont("medium") + color: UM.Theme.getColor("text") } Cura.TertiaryButton diff --git a/resources/qml/Widgets/TextField.qml b/resources/qml/Widgets/TextField.qml index 28074d4415..2643609eaf 100644 --- a/resources/qml/Widgets/TextField.qml +++ b/resources/qml/Widgets/TextField.qml @@ -15,6 +15,8 @@ TextField { id: textField + property alias leftIcon: iconLeft.source + UM.I18nCatalog { id: catalog; name: "cura" } hoverEnabled: true @@ -22,6 +24,7 @@ TextField font: UM.Theme.getFont("default") color: UM.Theme.getColor("text") renderType: Text.NativeRendering + leftPadding: iconLeft.visible ? iconLeft.width + UM.Theme.getSize("default_margin").width * 2 : UM.Theme.getSize("thin_margin") states: [ State @@ -67,5 +70,23 @@ TextField } return UM.Theme.getColor("setting_control_border") } + + //Optional icon added on the left hand side. + UM.RecolorImage + { + id: iconLeft + + anchors + { + verticalCenter: parent.verticalCenter + left: parent.left + leftMargin: UM.Theme.getSize("default_margin").width + } + + visible: source != "" + height: UM.Theme.getSize("small_button_icon").height + width: visible ? height : 0 + color: textField.color + } } } From 7fdf1dbdd4a511f626133547f7cb1eb1441f7e07 Mon Sep 17 00:00:00 2001 From: Ghostkeeper Date: Tue, 13 Jul 2021 16:02:29 +0200 Subject: [PATCH 42/96] Fix height of search bar Because this item is in a layout, the height gets overridden. We should use the preferredHeight, or the one it defaults to, implicitHeight. Contributes to issue CURA-8009. --- plugins/DigitalLibrary/resources/qml/SelectProjectPage.qml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/DigitalLibrary/resources/qml/SelectProjectPage.qml b/plugins/DigitalLibrary/resources/qml/SelectProjectPage.qml index 36e3de3da7..529f28213b 100644 --- a/plugins/DigitalLibrary/resources/qml/SelectProjectPage.qml +++ b/plugins/DigitalLibrary/resources/qml/SelectProjectPage.qml @@ -47,7 +47,7 @@ Item { id: searchBar Layout.fillWidth: true - height: createNewProjectButton.height + implicitHeight: createNewProjectButton.height onTextEdited: manager.projectFilter = text //Update the search filter when editing this text field. From 3d6601a37ecc176a6e26e2727d0e067fc46768dd Mon Sep 17 00:00:00 2001 From: Ghostkeeper Date: Tue, 13 Jul 2021 16:04:01 +0200 Subject: [PATCH 43/96] Fix margins The margin around the icon didn't work if the icon source was none, because it was provided a QSize rather than a real. The margin around the background didn't work at all because the background is automatically adjusted to fill the parent element, so it's best left out. Contributes to issue CURA-8009. --- resources/qml/Widgets/TextField.qml | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/resources/qml/Widgets/TextField.qml b/resources/qml/Widgets/TextField.qml index 2643609eaf..c126c8a6e0 100644 --- a/resources/qml/Widgets/TextField.qml +++ b/resources/qml/Widgets/TextField.qml @@ -1,4 +1,4 @@ -// Copyright (c) 2019 Ultimaker B.V. +// Copyright (c) 2021 Ultimaker B.V. // Cura is released under the terms of the LGPLv3 or higher. import QtQuick 2.10 @@ -24,7 +24,7 @@ TextField font: UM.Theme.getFont("default") color: UM.Theme.getColor("text") renderType: Text.NativeRendering - leftPadding: iconLeft.visible ? iconLeft.width + UM.Theme.getSize("default_margin").width * 2 : UM.Theme.getSize("thin_margin") + leftPadding: iconLeft.visible ? iconLeft.width + UM.Theme.getSize("default_margin").width * 2 : UM.Theme.getSize("thin_margin").width states: [ State @@ -55,7 +55,6 @@ TextField color: UM.Theme.getColor("main_background") - anchors.margins: Math.round(UM.Theme.getSize("default_lining").width) radius: UM.Theme.getSize("setting_control_radius").width border.color: From eb2a315e4234ff7bc78a50b2064fbf5d6bf1a658 Mon Sep 17 00:00:00 2001 From: Ghostkeeper Date: Tue, 13 Jul 2021 16:09:02 +0200 Subject: [PATCH 44/96] Specify spacing between search bar and button Instead of using the default of 5 pixels, we should use this element from the theme to match the margin around the page. Contributes to issue CURA-8009. --- plugins/DigitalLibrary/resources/qml/SelectProjectPage.qml | 1 + 1 file changed, 1 insertion(+) diff --git a/plugins/DigitalLibrary/resources/qml/SelectProjectPage.qml b/plugins/DigitalLibrary/resources/qml/SelectProjectPage.qml index 529f28213b..1a3c1723b3 100644 --- a/plugins/DigitalLibrary/resources/qml/SelectProjectPage.qml +++ b/plugins/DigitalLibrary/resources/qml/SelectProjectPage.qml @@ -42,6 +42,7 @@ Item right: parent.right } height: childrenRect.height + spacing: UM.Theme.getSize("default_margin").width Cura.TextField { From 72eb839d079dfb137e09af31cbd234d9ec887010 Mon Sep 17 00:00:00 2001 From: Ghostkeeper Date: Tue, 13 Jul 2021 16:18:36 +0200 Subject: [PATCH 45/96] Add missing search filter parameter to refresh query Thank you, automated tests. Contributes to issue CURA-8009. --- plugins/DigitalLibrary/src/DigitalFactoryController.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/DigitalLibrary/src/DigitalFactoryController.py b/plugins/DigitalLibrary/src/DigitalFactoryController.py index 796937a9d9..5f160a4b8f 100644 --- a/plugins/DigitalLibrary/src/DigitalFactoryController.py +++ b/plugins/DigitalLibrary/src/DigitalFactoryController.py @@ -555,7 +555,7 @@ class DigitalFactoryController(QObject): # false, we also need to clean it from the projects model self._project_model.clearProjects() self.setSelectedProjectIndex(-1) - self._api.getProjectsFirstPage(on_finished = self._onGetProjectsFirstPageFinished, failed = self._onGetProjectsFailed) + self._api.getProjectsFirstPage(search_filter = self._project_filter, on_finished = self._onGetProjectsFirstPageFinished, failed = self._onGetProjectsFailed) self.setRetrievingProjectsStatus(RetrievalStatus.InProgress) self._has_preselected_project = new_has_preselected_project self.preselectedProjectChanged.emit() From 7f2e951b9c8ccfdd2f2be2ad6308299cc8ea88bb Mon Sep 17 00:00:00 2001 From: Ghostkeeper Date: Tue, 13 Jul 2021 16:24:21 +0200 Subject: [PATCH 46/96] Update tests to test filter too Contributes to issue CURA-8009. --- .../tests/TestDigitalLibraryApiClient.py | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/plugins/DigitalLibrary/tests/TestDigitalLibraryApiClient.py b/plugins/DigitalLibrary/tests/TestDigitalLibraryApiClient.py index ba0a0b15b4..9751838ddf 100644 --- a/plugins/DigitalLibrary/tests/TestDigitalLibraryApiClient.py +++ b/plugins/DigitalLibrary/tests/TestDigitalLibraryApiClient.py @@ -1,3 +1,6 @@ +# Copyright (c) 2021 Ultimaker B.V. +# Cura is released under the terms of the LGPLv3 or higher. + from unittest.mock import MagicMock import pytest @@ -37,7 +40,7 @@ def test_getProjectsFirstPage(api_client): failed_callback = MagicMock() # Call - api_client.getProjectsFirstPage(on_finished = finished_callback, failed = failed_callback) + api_client.getProjectsFirstPage(search_filter = "filter", on_finished = finished_callback, failed = failed_callback) # Asserts pagination_manager.reset.assert_called_once() # Should be called since we asked for new set of projects @@ -45,16 +48,16 @@ def test_getProjectsFirstPage(api_client): args = http_manager.get.call_args_list[0] # Ensure that it's called with the right limit - assert args[0][0] == "https://api.ultimaker.com/cura/v1/projects?limit=20" + assert args[0][0] == "https://api.ultimaker.com/cura/v1/projects?limit=20&search=filter" # Change the limit & try again http_manager.get.reset_mock() pagination_manager.limit = 80 - api_client.getProjectsFirstPage(on_finished = finished_callback, failed = failed_callback) + api_client.getProjectsFirstPage(search_filter = "filter", on_finished = finished_callback, failed = failed_callback) args = http_manager.get.call_args_list[0] # Ensure that it's called with the right limit - assert args[0][0] == "https://api.ultimaker.com/cura/v1/projects?limit=80" + assert args[0][0] == "https://api.ultimaker.com/cura/v1/projects?limit=80&search=filter" def test_getMoreProjects_noNewProjects(api_client): From 6560766b1ffc5dd83c6eebf45d7754b77007b925 Mon Sep 17 00:00:00 2001 From: Victor Lin <60565737+v-xup6@users.noreply.github.com> Date: Tue, 13 Jul 2021 22:40:39 +0800 Subject: [PATCH 47/96] Update atom2.def.json Simplify brim width to adjust only the value --- resources/definitions/atom2.def.json | 32 ++-------------------------- 1 file changed, 2 insertions(+), 30 deletions(-) diff --git a/resources/definitions/atom2.def.json b/resources/definitions/atom2.def.json index 8fbbe2c698..d7a26546d8 100644 --- a/resources/definitions/atom2.def.json +++ b/resources/definitions/atom2.def.json @@ -30,34 +30,6 @@ "speed_print": { "default_value": 32 }, "optimize_wall_printing_order": { "value": "True" }, "infill_sparse_density": { "default_value": 10 }, - "brim_width": - { - "label": "Brim Width", - "description": "The distance from the model to the outermost brim line. A larger brim enhances adhesion to the build plate, but also reduces the effective print area.", - "type": "float", - "unit": "mm", - "default_value": 4, - "minimum_value": "0.0", - "maximum_value_warning": "50.0", - "maximum_value": "0.5 * min(machine_width, machine_depth)", - "enabled": "resolveOrValue('adhesion_type') == 'brim' or resolveOrValue('prime_tower_brim_enable')", - "settable_per_mesh": false, - "children": - { - "brim_line_count": - { - "label": "Brim Line Count", - "description": "The number of lines used for a brim. More brim lines enhance adhesion to the build plate, but also reduces the effective print area.", - "type": "int", - "default_value": 10, - "minimum_value": "0", - "maximum_value_warning": "50 / skirt_brim_line_width", - "maximum_value": "0.5 * min(machine_width, machine_depth) / skirt_brim_line_width", - "value": 10, - "enabled": "resolveOrValue('adhesion_type') == 'brim' or resolveOrValue('prime_tower_brim_enable')", - "settable_per_mesh": false - } - } - } + "brim_width": { "default_value": 4 } } -} \ No newline at end of file +} From 8414e8b52372372ea54554fcfc44512257a4f206 Mon Sep 17 00:00:00 2001 From: Victor Lin <60565737+v-xup6@users.noreply.github.com> Date: Tue, 13 Jul 2021 22:42:03 +0800 Subject: [PATCH 48/96] Delete atomPlus.def.json Prototype machine --- resources/definitions/atomPlus.def.json | 34 ------------------------- 1 file changed, 34 deletions(-) delete mode 100644 resources/definitions/atomPlus.def.json diff --git a/resources/definitions/atomPlus.def.json b/resources/definitions/atomPlus.def.json deleted file mode 100644 index 2d053693ff..0000000000 --- a/resources/definitions/atomPlus.def.json +++ /dev/null @@ -1,34 +0,0 @@ -{ - "name": "Atom Plus", - "version": 2, - "inherits": "fdmprinter", - "metadata": { - "visible": true, - "author": "Victor (Yu Chieh) Lin", - "manufacturer": "Layer One", - "file_formats": "text/x-gcode", - "platform_offset": [0,0,0], - "machine_extruder_trains": { "0": "atomPlus_extruder_0" - } - }, - - "overrides": { - "machine_name": { "default_value": "Atom Plus" }, - "machine_shape": { "default_value": "elliptic" }, - "machine_width": { "default_value": 420 }, - "machine_depth": { "default_value": 420 }, - "machine_height": { "default_value": 910 }, - "machine_extruder_count": { "default_value": 1 }, - "machine_heated_bed": { "default_value": false }, - "machine_center_is_zero": { "default_value": true }, - - "machine_start_gcode": { "default_value": "G21\nG90 \nM107\nG28\nG92 E0\nG1 F200 E3\nG92 E0" }, - "machine_end_gcode": { "default_value": "M104 S0\nG28\nG91\nG1 E-6 F300\nM84\nG90" }, - - "layer_height": { "default_value": 0.4 }, - "default_material_print_temperature": { "default_value": 220 }, - "speed_print": { "default_value": 32 }, - "optimize_wall_printing_order": { "value": "True" }, - "infill_sparse_density": { "default_value": 10 } - } -} \ No newline at end of file From 52b022c575bfb6205b5094866da6a8046d0e9056 Mon Sep 17 00:00:00 2001 From: Victor Lin <60565737+v-xup6@users.noreply.github.com> Date: Tue, 13 Jul 2021 22:42:12 +0800 Subject: [PATCH 49/96] Delete atomPlus_extruder_0.def.json Prototype machine --- resources/extruders/atomPlus_extruder_0.def.json | 15 --------------- 1 file changed, 15 deletions(-) delete mode 100644 resources/extruders/atomPlus_extruder_0.def.json diff --git a/resources/extruders/atomPlus_extruder_0.def.json b/resources/extruders/atomPlus_extruder_0.def.json deleted file mode 100644 index 19ab13cf79..0000000000 --- a/resources/extruders/atomPlus_extruder_0.def.json +++ /dev/null @@ -1,15 +0,0 @@ -{ - "version": 2, - "name": "Extruder 1", - "inherits": "fdmextruder", - "metadata": { - "machine": "atomPlus", - "position": "0" - }, - - "overrides": { - "extruder_nr": { "default_value": 0 }, - "machine_nozzle_size": { "default_value": 1 }, - "material_diameter": { "default_value": 1.75 } - } -} From 9d8286d90c79ca891986e44d886dc3666fa9ed79 Mon Sep 17 00:00:00 2001 From: Konstantinos Karmas Date: Tue, 13 Jul 2021 16:52:36 +0200 Subject: [PATCH 50/96] Set the correct initial value in the feature budget attributes They were defined as `Optional[int]` but started with the default value as `False`. CURA-8112 --- .../src/DigitalFactoryFeatureBudgetResponse.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/plugins/DigitalLibrary/src/DigitalFactoryFeatureBudgetResponse.py b/plugins/DigitalLibrary/src/DigitalFactoryFeatureBudgetResponse.py index 016306a478..192f58685a 100644 --- a/plugins/DigitalLibrary/src/DigitalFactoryFeatureBudgetResponse.py +++ b/plugins/DigitalLibrary/src/DigitalFactoryFeatureBudgetResponse.py @@ -16,9 +16,9 @@ class DigitalFactoryFeatureBudgetResponse(BaseModel): library_can_use_status: Optional[bool] = False, library_can_use_tags: Optional[bool] = False, library_can_use_technical_requirements: Optional[bool] = False, - library_max_organization_shared_projects: Optional[int] = False, # -1 means unlimited - library_max_private_projects: Optional[int] = False, # -1 means unlimited - library_max_team_shared_projects: Optional[int] = False, # -1 means unlimited + library_max_organization_shared_projects: Optional[int] = None, # -1 means unlimited + library_max_private_projects: Optional[int] = None, # -1 means unlimited + library_max_team_shared_projects: Optional[int] = None, # -1 means unlimited **kwargs) -> None: self.library_can_use_business_value = library_can_use_business_value From 9ddb3b7713c48856acd8a6748202099123dbd6d0 Mon Sep 17 00:00:00 2001 From: Konstantinos Karmas Date: Tue, 13 Jul 2021 16:53:02 +0200 Subject: [PATCH 51/96] Fix icon being ignored in message action buttons CURA-8112 --- resources/qml/Cura.qml | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/resources/qml/Cura.qml b/resources/qml/Cura.qml index 191ae712d4..80b8880aae 100644 --- a/resources/qml/Cura.qml +++ b/resources/qml/Cura.qml @@ -417,6 +417,7 @@ UM.MainWindow Cura.PrimaryButton { text: model.name + iconSource: UM.Theme.getIcon(model.icon) height: UM.Theme.getSize("message_action_button").height } } @@ -426,6 +427,7 @@ UM.MainWindow Cura.SecondaryButton { text: model.name + iconSource: UM.Theme.getIcon(model.icon) height: UM.Theme.getSize("message_action_button").height } } @@ -434,6 +436,11 @@ UM.MainWindow Cura.TertiaryButton { text: model.name + iconSource: { + if (model.icon == null || model.icon == "") + return UM.Theme.getIcon("LinkExternal") + return UM.Theme.getIcon(model.icon) + } height: UM.Theme.getSize("message_action_button").height } } From 888f62a9ea39eefc705d658bfc2da6f1b8d5936b Mon Sep 17 00:00:00 2001 From: Jaime van Kessel Date: Tue, 13 Jul 2021 16:55:28 +0200 Subject: [PATCH 52/96] Add missing typing CURA-8009 --- plugins/DigitalLibrary/src/DigitalFactoryController.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/plugins/DigitalLibrary/src/DigitalFactoryController.py b/plugins/DigitalLibrary/src/DigitalFactoryController.py index 5f160a4b8f..9c412a9747 100644 --- a/plugins/DigitalLibrary/src/DigitalFactoryController.py +++ b/plugins/DigitalLibrary/src/DigitalFactoryController.py @@ -310,7 +310,7 @@ class DigitalFactoryController(QObject): self._selected_file_indices = file_indices self.selectedFileIndicesChanged.emit(file_indices) - def setProjectFilter(self, new_filter) -> None: + def setProjectFilter(self, new_filter: str) -> None: """ Called when the user wants to change the search filter for projects. @@ -333,7 +333,7 @@ class DigitalFactoryController(QObject): """ return self._project_filter - def _applyProjectFilter(self): + def _applyProjectFilter(self) -> None: """ Actually apply the current filter to search for projects with the user-defined search string. :return: From 2d45b8c2cd7ca7e72b44b16c7543299e1688b4b5 Mon Sep 17 00:00:00 2001 From: Konstantinos Karmas Date: Tue, 13 Jul 2021 17:28:38 +0200 Subject: [PATCH 53/96] Show an "Upgrade plan" button to users that have reached maximum projects Instead of letting users go through the project creation process only to get rejected with a "subscription limits reached" message, now the "New Library project" button is being replaced with an "Upgrade plan" button when the maximum allowed projects have been reached for the specific amount. The button is accompanied by a tooltip that explains the situation to the user. Once clicked, the user is redirected to the subscriptions page. CURA-8112 --- .../resources/qml/SelectProjectPage.qml | 17 +++++++++++++- .../src/DigitalFactoryApiClient.py | 23 +++++++++++++++++++ .../src/DigitalFactoryController.py | 18 +++++++++++++++ 3 files changed, 57 insertions(+), 1 deletion(-) diff --git a/plugins/DigitalLibrary/resources/qml/SelectProjectPage.qml b/plugins/DigitalLibrary/resources/qml/SelectProjectPage.qml index 2de0e78cc7..0f8544285f 100644 --- a/plugins/DigitalLibrary/resources/qml/SelectProjectPage.qml +++ b/plugins/DigitalLibrary/resources/qml/SelectProjectPage.qml @@ -18,7 +18,7 @@ Item width: parent.width height: parent.height - property alias createNewProjectButtonVisible: createNewProjectButton.visible + property bool createNewProjectButtonVisible: true anchors { @@ -48,6 +48,7 @@ Item anchors.verticalCenter: selectProjectLabel.verticalCenter anchors.right: parent.right text: "New Library project" + visible: createNewProjectButtonVisible && manager.userAccountCanCreateNewLibraryProject && (manager.retrievingProjectsStatus == DF.RetrievalStatus.Success || manager.retrievingProjectsStatus == DF.RetrievalStatus.Failed) onClicked: { @@ -56,6 +57,20 @@ Item busy: manager.creatingNewProjectStatus == DF.RetrievalStatus.InProgress } + + Cura.SecondaryButton + { + id: upgradePlanButton + + anchors.verticalCenter: selectProjectLabel.verticalCenter + anchors.right: parent.right + text: "Upgrade plan" + visible: createNewProjectButtonVisible && !manager.userAccountCanCreateNewLibraryProject && (manager.retrievingProjectsStatus == DF.RetrievalStatus.Success || manager.retrievingProjectsStatus == DF.RetrievalStatus.Failed) + tooltip: "You have reached the maximum number of projects allowed by your subscription. Please upgrade to the Professional subscription to create more projects." + + onClicked: Qt.openUrlExternally("https://ultimaker.com/software/enterprise-software") + } + Item { id: noLibraryProjectsContainer diff --git a/plugins/DigitalLibrary/src/DigitalFactoryApiClient.py b/plugins/DigitalLibrary/src/DigitalFactoryApiClient.py index e1a62fdd5c..acb7b9a5a5 100644 --- a/plugins/DigitalLibrary/src/DigitalFactoryApiClient.py +++ b/plugins/DigitalLibrary/src/DigitalFactoryApiClient.py @@ -55,6 +55,7 @@ class DigitalFactoryApiClient: self._http = HttpRequestManager.getInstance() self._on_error = on_error self._file_uploader = None # type: Optional[DFFileUploader] + self._library_max_private_projects: Optional[int] = None self._projects_pagination_mgr = PaginationManager(limit = projects_limit_per_page) if projects_limit_per_page else None # type: Optional[PaginationManager] @@ -69,6 +70,7 @@ class DigitalFactoryApiClient: callback( response.library_max_private_projects == -1 or # Note: -1 is unlimited response.library_max_private_projects > 0) + self._library_max_private_projects = response.library_max_private_projects else: Logger.warning(f"Digital Factory: Response is not a feature budget, likely an error: {str(response)}") callback(False) @@ -79,6 +81,27 @@ class DigitalFactoryApiClient: error_callback = callbackWrap, timeout = self.DEFAULT_REQUEST_TIMEOUT) + def checkUserCanCreateNewLibraryProject(self, callback: Callable) -> None: + """ + Checks if the user is allowed to create new library projects. + A user is allowed to create new library projects if the haven't reached their maximum allowed private projects. + """ + + def callbackWrap(response: Optional[Any] = None, *args, **kwargs) -> None: + if response is not None: + if self._library_max_private_projects == -1 or isinstance(response, DigitalFactoryProjectResponse): + callback(True) + elif isinstance(response, list) and all(isinstance(r, DigitalFactoryProjectResponse) for r in response): + callback(len(response) < self._library_max_private_projects) + else: + Logger.warning(f"Digital Factory: Incorrect response type received when requesting private projects: {str(response)}") + callback(False) + else: + Logger.warning(f"Digital Factory: Response is empty, likely an error: {str(response)}") + callback(False) + + self.getProjectsFirstPage(on_finished = callbackWrap, failed = callbackWrap) + def getProject(self, library_project_id: str, on_finished: Callable[[DigitalFactoryProjectResponse], Any], failed: Callable) -> None: """ Retrieves a digital factory project by its library project id. diff --git a/plugins/DigitalLibrary/src/DigitalFactoryController.py b/plugins/DigitalLibrary/src/DigitalFactoryController.py index 368b29219a..cf4174d7c9 100644 --- a/plugins/DigitalLibrary/src/DigitalFactoryController.py +++ b/plugins/DigitalLibrary/src/DigitalFactoryController.py @@ -92,6 +92,9 @@ class DigitalFactoryController(QObject): """Signal to inform about the state of user access.""" userAccessStateChanged = pyqtSignal(bool) + """Signal to inform whether the user is allowed to create more Library projects.""" + userCanCreateNewLibraryProjectChanged = pyqtSignal(bool) + def __init__(self, application: CuraApplication) -> None: super().__init__(parent = None) @@ -136,6 +139,7 @@ class DigitalFactoryController(QObject): self._application.initializationFinished.connect(self._applicationInitializationFinished) self._user_has_access = False + self._user_account_can_create_new_project = False def clear(self) -> None: self._project_model.clearProjects() @@ -166,6 +170,11 @@ class DigitalFactoryController(QObject): subscriptions = self._account.userProfile.get("subscriptions", []) if len(subscriptions) > 0: return True + if self._user_has_access: + # The user has access even though they have no subscriptions. This means they are an Essential user and they + # have limited personal private projects available. In this case, we need to check whether they have already + # reached their limit. + self._api.checkUserCanCreateNewLibraryProject(callback = self.setCanCreateNewLibraryProject) return self._user_has_access def initialize(self, preselected_project_id: Optional[str] = None) -> None: @@ -517,6 +526,7 @@ class DigitalFactoryController(QObject): self._project_model.clearProjects() self.setSelectedProjectIndex(-1) self._api.getProjectsFirstPage(on_finished = self._onGetProjectsFirstPageFinished, failed = self._onGetProjectsFailed) + self._api.checkUserCanCreateNewLibraryProject(callback = self.setCanCreateNewLibraryProject) self.setRetrievingProjectsStatus(RetrievalStatus.InProgress) self._has_preselected_project = new_has_preselected_project self.preselectedProjectChanged.emit() @@ -525,6 +535,14 @@ class DigitalFactoryController(QObject): def hasPreselectedProject(self) -> bool: return self._has_preselected_project + def setCanCreateNewLibraryProject(self, can_create_new_library_project: bool) -> None: + self._user_account_can_create_new_project = can_create_new_library_project + self.userCanCreateNewLibraryProjectChanged.emit(self._user_account_can_create_new_project) + + @pyqtProperty(bool, fset = setCanCreateNewLibraryProject, notify = userCanCreateNewLibraryProjectChanged) + def userAccountCanCreateNewLibraryProject(self) -> bool: + return self._user_account_can_create_new_project + @pyqtSlot(str, "QStringList") def saveFileToSelectedProject(self, filename: str, formats: List[str]) -> None: """ From f643f19af63c649bd94d292cc627eb6ec177c479 Mon Sep 17 00:00:00 2001 From: Konstantinos Karmas Date: Tue, 13 Jul 2021 17:30:30 +0200 Subject: [PATCH 54/96] Fix tooltip not shown when the tooltip text is too long When the tooltip text is too long and the tooltip width ends up being longer than the window it is supposed to be drawn into, the tooltip is not drawn at all. This commit fixed that by allowing the tooltip width of the ActionButton to be changed within QML, limiting it to a certain size that fits the purpose. CURA-8112 --- plugins/DigitalLibrary/resources/qml/SelectProjectPage.qml | 1 + resources/qml/ActionButton.qml | 1 + 2 files changed, 2 insertions(+) diff --git a/plugins/DigitalLibrary/resources/qml/SelectProjectPage.qml b/plugins/DigitalLibrary/resources/qml/SelectProjectPage.qml index 0f8544285f..b638082853 100644 --- a/plugins/DigitalLibrary/resources/qml/SelectProjectPage.qml +++ b/plugins/DigitalLibrary/resources/qml/SelectProjectPage.qml @@ -67,6 +67,7 @@ Item text: "Upgrade plan" visible: createNewProjectButtonVisible && !manager.userAccountCanCreateNewLibraryProject && (manager.retrievingProjectsStatus == DF.RetrievalStatus.Success || manager.retrievingProjectsStatus == DF.RetrievalStatus.Failed) tooltip: "You have reached the maximum number of projects allowed by your subscription. Please upgrade to the Professional subscription to create more projects." + tooltipWidth: parent.width * 3 / 4 onClicked: Qt.openUrlExternally("https://ultimaker.com/software/enterprise-software") } diff --git a/resources/qml/ActionButton.qml b/resources/qml/ActionButton.qml index 31d5c35d2c..582df3d87c 100644 --- a/resources/qml/ActionButton.qml +++ b/resources/qml/ActionButton.qml @@ -18,6 +18,7 @@ Button property alias textFont: buttonText.font property alias cornerRadius: backgroundRect.radius property alias tooltip: tooltip.tooltipText + property alias tooltipWidth: tooltip.width property color color: UM.Theme.getColor("primary") property color hoverColor: UM.Theme.getColor("primary_hover") From 2961d20c04ff5262d29dd69d65b6e0ccb78c57af Mon Sep 17 00:00:00 2001 From: Konstantinos Karmas Date: Tue, 13 Jul 2021 17:38:15 +0200 Subject: [PATCH 55/96] Fix mypy complaint CURA-8112 --- plugins/DigitalLibrary/src/DigitalFactoryApiClient.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/DigitalLibrary/src/DigitalFactoryApiClient.py b/plugins/DigitalLibrary/src/DigitalFactoryApiClient.py index acb7b9a5a5..c0c6099b0d 100644 --- a/plugins/DigitalLibrary/src/DigitalFactoryApiClient.py +++ b/plugins/DigitalLibrary/src/DigitalFactoryApiClient.py @@ -91,7 +91,7 @@ class DigitalFactoryApiClient: if response is not None: if self._library_max_private_projects == -1 or isinstance(response, DigitalFactoryProjectResponse): callback(True) - elif isinstance(response, list) and all(isinstance(r, DigitalFactoryProjectResponse) for r in response): + elif isinstance(response, list) and all(isinstance(r, DigitalFactoryProjectResponse) for r in response) and self._library_max_private_projects is not None: callback(len(response) < self._library_max_private_projects) else: Logger.warning(f"Digital Factory: Incorrect response type received when requesting private projects: {str(response)}") From 11f66b2a78bc6d29ac8f47b4ef9659b065854357 Mon Sep 17 00:00:00 2001 From: Konstantinos Karmas Date: Wed, 14 Jul 2021 12:54:31 +0200 Subject: [PATCH 56/96] Add brackets CURA-8112 --- resources/qml/Cura.qml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/resources/qml/Cura.qml b/resources/qml/Cura.qml index 80b8880aae..e91dd39091 100644 --- a/resources/qml/Cura.qml +++ b/resources/qml/Cura.qml @@ -438,7 +438,9 @@ UM.MainWindow text: model.name iconSource: { if (model.icon == null || model.icon == "") + { return UM.Theme.getIcon("LinkExternal") + } return UM.Theme.getIcon(model.icon) } height: UM.Theme.getSize("message_action_button").height From 3dbbe7276baa3b201698e19bfbacbef45a3d8464 Mon Sep 17 00:00:00 2001 From: Konstantinos Karmas Date: Wed, 14 Jul 2021 12:55:28 +0200 Subject: [PATCH 57/96] Remove check for account subscriptions Since the variable `self._user_has_access` already contains the information on whether the user can access the Digital Library. CURA-8112 --- plugins/DigitalLibrary/src/DigitalFactoryController.py | 7 ------- 1 file changed, 7 deletions(-) diff --git a/plugins/DigitalLibrary/src/DigitalFactoryController.py b/plugins/DigitalLibrary/src/DigitalFactoryController.py index cf4174d7c9..5caaca2e25 100644 --- a/plugins/DigitalLibrary/src/DigitalFactoryController.py +++ b/plugins/DigitalLibrary/src/DigitalFactoryController.py @@ -166,14 +166,7 @@ class DigitalFactoryController(QObject): :return: True if the user account has Digital Library access, else False """ - if self._account.userProfile: - subscriptions = self._account.userProfile.get("subscriptions", []) - if len(subscriptions) > 0: - return True if self._user_has_access: - # The user has access even though they have no subscriptions. This means they are an Essential user and they - # have limited personal private projects available. In this case, we need to check whether they have already - # reached their limit. self._api.checkUserCanCreateNewLibraryProject(callback = self.setCanCreateNewLibraryProject) return self._user_has_access From 300176cdc69d728fc27a01a35356a2d37eb51186 Mon Sep 17 00:00:00 2001 From: Konstantinos Karmas Date: Wed, 14 Jul 2021 13:03:03 +0200 Subject: [PATCH 58/96] Check for the maximum **private** projects When checking whether the user is allowed to create a new library project, we need to retrieve the **private** (aka non-shared) projects that are linked to the user's account. If the user has reached the maximum private projects, then they are no longer allowed to create new ones. **Note**: We need to set the `pagination_manager` to `None` when doing this get request, or else the next/previous links of the pagination will become mixed up with the pagination links of the list of projects shown to the user, corrupting them and creating the wrong "get more projects" link. CURA-8112 --- .../src/DigitalFactoryApiClient.py | 20 ++++++++++++++++--- 1 file changed, 17 insertions(+), 3 deletions(-) diff --git a/plugins/DigitalLibrary/src/DigitalFactoryApiClient.py b/plugins/DigitalLibrary/src/DigitalFactoryApiClient.py index c0c6099b0d..91f1daf2f7 100644 --- a/plugins/DigitalLibrary/src/DigitalFactoryApiClient.py +++ b/plugins/DigitalLibrary/src/DigitalFactoryApiClient.py @@ -89,9 +89,9 @@ class DigitalFactoryApiClient: def callbackWrap(response: Optional[Any] = None, *args, **kwargs) -> None: if response is not None: - if self._library_max_private_projects == -1 or isinstance(response, DigitalFactoryProjectResponse): + if isinstance(response, DigitalFactoryProjectResponse): # The user has only one private project callback(True) - elif isinstance(response, list) and all(isinstance(r, DigitalFactoryProjectResponse) for r in response) and self._library_max_private_projects is not None: + elif isinstance(response, list) and all(isinstance(r, DigitalFactoryProjectResponse) for r in response): callback(len(response) < self._library_max_private_projects) else: Logger.warning(f"Digital Factory: Incorrect response type received when requesting private projects: {str(response)}") @@ -100,7 +100,21 @@ class DigitalFactoryApiClient: Logger.warning(f"Digital Factory: Response is empty, likely an error: {str(response)}") callback(False) - self.getProjectsFirstPage(on_finished = callbackWrap, failed = callbackWrap) + if self._library_max_private_projects is not None and self._library_max_private_projects > 0: + # The user has a limit in the number of private projects they can create. Check whether they have already + # reached that limit. + # Note: Set the pagination manager to None when doing this get request, or else the next/previous links + # of the pagination will become corrupted + url = f"{self.CURA_API_ROOT}/projects?shared=false&limit={self._library_max_private_projects}" + self._http.get(url, + scope = self._scope, + callback = self._parseCallback(callbackWrap, DigitalFactoryProjectResponse, callbackWrap, pagination_manager = None), + error_callback = callbackWrap, + timeout = self.DEFAULT_REQUEST_TIMEOUT) + else: + # If the limit is -1, then the user is allowed unlimited projects. If its 0 then they are not allowed to + # create any projects + callback(self._library_max_private_projects == -1) def getProject(self, library_project_id: str, on_finished: Callable[[DigitalFactoryProjectResponse], Any], failed: Callable) -> None: """ From 7027a8f904311251f0d20e1a02061d226986f72a Mon Sep 17 00:00:00 2001 From: Konstantinos Karmas Date: Wed, 14 Jul 2021 13:08:51 +0200 Subject: [PATCH 59/96] Fix mypy complaint again Mypy doesn't recognize that the check for `None` has happened before calling the `callbackWrap` (before the get request has been made). CURA-8112 --- plugins/DigitalLibrary/src/DigitalFactoryApiClient.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/DigitalLibrary/src/DigitalFactoryApiClient.py b/plugins/DigitalLibrary/src/DigitalFactoryApiClient.py index 91f1daf2f7..460438e365 100644 --- a/plugins/DigitalLibrary/src/DigitalFactoryApiClient.py +++ b/plugins/DigitalLibrary/src/DigitalFactoryApiClient.py @@ -92,7 +92,7 @@ class DigitalFactoryApiClient: if isinstance(response, DigitalFactoryProjectResponse): # The user has only one private project callback(True) elif isinstance(response, list) and all(isinstance(r, DigitalFactoryProjectResponse) for r in response): - callback(len(response) < self._library_max_private_projects) + callback(len(response) < cast(int, self._library_max_private_projects)) else: Logger.warning(f"Digital Factory: Incorrect response type received when requesting private projects: {str(response)}") callback(False) From 016371d77160eb07b9187fd65157ded2b535caac Mon Sep 17 00:00:00 2001 From: Konstantinos Karmas Date: Wed, 14 Jul 2021 14:34:00 +0200 Subject: [PATCH 60/96] Add the external link icon to the Upgrade plan button CURA-8112 --- plugins/DigitalLibrary/resources/qml/SelectProjectPage.qml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/plugins/DigitalLibrary/resources/qml/SelectProjectPage.qml b/plugins/DigitalLibrary/resources/qml/SelectProjectPage.qml index b638082853..a4eefd13f6 100644 --- a/plugins/DigitalLibrary/resources/qml/SelectProjectPage.qml +++ b/plugins/DigitalLibrary/resources/qml/SelectProjectPage.qml @@ -65,9 +65,10 @@ Item anchors.verticalCenter: selectProjectLabel.verticalCenter anchors.right: parent.right text: "Upgrade plan" + iconSource: UM.Theme.getIcon("LinkExternal") visible: createNewProjectButtonVisible && !manager.userAccountCanCreateNewLibraryProject && (manager.retrievingProjectsStatus == DF.RetrievalStatus.Success || manager.retrievingProjectsStatus == DF.RetrievalStatus.Failed) tooltip: "You have reached the maximum number of projects allowed by your subscription. Please upgrade to the Professional subscription to create more projects." - tooltipWidth: parent.width * 3 / 4 + tooltipWidth: parent.width * 0.5 onClicked: Qt.openUrlExternally("https://ultimaker.com/software/enterprise-software") } From fd322c051258c089b41c83d5d86b2b2a6eec1913 Mon Sep 17 00:00:00 2001 From: Konstantinos Karmas Date: Wed, 14 Jul 2021 15:32:57 +0200 Subject: [PATCH 61/96] Fix having no "load more projects" available when using the search When the `_onGetProjectsFirstPageFinished` is reached, the pagination manager already contains the correct pagination metadata and links, so calling `clear()` there resets them giving the impression that there is no next page. This commit fixed that by calling the `clear()` function should when the search filter is applied, instead. CURA-8009 --- plugins/DigitalLibrary/src/DigitalFactoryController.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/DigitalLibrary/src/DigitalFactoryController.py b/plugins/DigitalLibrary/src/DigitalFactoryController.py index 9c412a9747..0821cc6925 100644 --- a/plugins/DigitalLibrary/src/DigitalFactoryController.py +++ b/plugins/DigitalLibrary/src/DigitalFactoryController.py @@ -211,7 +211,6 @@ class DigitalFactoryController(QObject): :param df_projects: A list of all the Digital Factory Library projects linked to the user's account """ - self.clear() self.setHasMoreProjectsToLoad(self._api.hasMoreProjectsToLoad()) self._project_model.setProjects(df_projects) self.setRetrievingProjectsStatus(RetrievalStatus.Success) @@ -338,6 +337,7 @@ class DigitalFactoryController(QObject): Actually apply the current filter to search for projects with the user-defined search string. :return: """ + self.clear() self.projectFilterChanged.emit() self._api.getProjectsFirstPage(search_filter = self._project_filter, on_finished = self._onGetProjectsFirstPageFinished, failed = self._onGetProjectsFailed) From e9ecba13746482d0d1e183a641f9577a1a63085a Mon Sep 17 00:00:00 2001 From: Jaime van Kessel Date: Wed, 14 Jul 2021 16:03:06 +0200 Subject: [PATCH 62/96] Remove bindingloop in project selector --- plugins/DigitalLibrary/resources/qml/SelectProjectPage.qml | 2 -- 1 file changed, 2 deletions(-) diff --git a/plugins/DigitalLibrary/resources/qml/SelectProjectPage.qml b/plugins/DigitalLibrary/resources/qml/SelectProjectPage.qml index 1a3c1723b3..d184264cde 100644 --- a/plugins/DigitalLibrary/resources/qml/SelectProjectPage.qml +++ b/plugins/DigitalLibrary/resources/qml/SelectProjectPage.qml @@ -93,8 +93,6 @@ Item source: searchBar.text === "" ? "../images/digital_factory.svg" : "../images/projects_not_found.svg" fillMode: Image.PreserveAspectFit width: parent.width - 2 * UM.Theme.getSize("thick_margin").width - sourceSize.width: width - sourceSize.height: height } Label From 399b378ba65499b04ccf25916f4b6d8d1dc23b38 Mon Sep 17 00:00:00 2001 From: Ghostkeeper Date: Wed, 14 Jul 2021 16:58:05 +0200 Subject: [PATCH 63/96] Show message when slicing failed with nonzero exit code The slicing engine should never crash. If it does though, it's best to show something to the user. Otherwise the slicing process just halts and the user will wait a long time for it to never finish. Contributes to issue CURA-6568. --- .../CuraEngineBackend/CuraEngineBackend.py | 28 +++++++++++++++++-- 1 file changed, 25 insertions(+), 3 deletions(-) diff --git a/plugins/CuraEngineBackend/CuraEngineBackend.py b/plugins/CuraEngineBackend/CuraEngineBackend.py index 1aa6c86dcb..4c0ed55bfe 100755 --- a/plugins/CuraEngineBackend/CuraEngineBackend.py +++ b/plugins/CuraEngineBackend/CuraEngineBackend.py @@ -4,12 +4,12 @@ import argparse #To run the engine in debug mode if the front-end is in debug mode. from collections import defaultdict import os -from PyQt5.QtCore import QObject, QTimer, pyqtSlot +from PyQt5.QtCore import QObject, QTimer, QUrl, pyqtSlot import sys from time import time from typing import Any, cast, Dict, List, Optional, Set, TYPE_CHECKING -from PyQt5.QtGui import QImage +from PyQt5.QtGui import QDesktopServices, QImage from UM.Backend.Backend import Backend, BackendState from UM.Scene.SceneNode import SceneNode @@ -922,9 +922,31 @@ class CuraEngineBackend(QObject, Backend): if not self._restart: if self._process: # type: ignore - Logger.log("d", "Backend quit with return code %s. Resetting process and socket.", self._process.wait()) # type: ignore + return_code = self._process.wait() + if return_code != 0: + Logger.log("e", f"Backend exited abnormally with return code {return_code}!") + message = Message( + text = catalog.i18nc("@message", "Slicing failed with an unexpected error. Please consider reporting a bug on our issue tracker."), + title = catalog.i18nc("@message:title", "Slicing failed") + ) + message.addAction( + action_id = "report_bug", + name = catalog.i18nc("@message:button", "Report a bug"), + description = catalog.i18nc("@message:description", "Report a bug on Ultimaker Cura's issue tracker."), + icon = "[no_icon]" + ) + message.actionTriggered.connect(self._reportBackendError) + message.show() + else: + Logger.log("d", "Backend finished slicing. Resetting process and socket.") self._process = None # type: ignore + def _reportBackendError(self, _message_id: str, _action_id: str) -> None: + """ + Triggered when the user wants to report an error in the back-end. + """ + QDesktopServices.openUrl(QUrl("https://github.com/Ultimaker/Cura/issues/new/choose")) + def _onGlobalStackChanged(self) -> None: """Called when the global container stack changes""" From 26487c5b3147923edddde41e8b052793ffd3eda5 Mon Sep 17 00:00:00 2001 From: Ghostkeeper Date: Wed, 14 Jul 2021 17:02:55 +0200 Subject: [PATCH 64/96] Stop slicing if an error occurred If the user has auto-slicing enabled, this causes the indeterminate progress bar to appear. If the user doesn't have auto-slicing enabled, this causes the slice button to reappear. Both of these indicate that something has caused slicing to be interrupted. The message should make clear why. Contributes to issue CURA-6568. --- plugins/CuraEngineBackend/CuraEngineBackend.py | 1 + 1 file changed, 1 insertion(+) diff --git a/plugins/CuraEngineBackend/CuraEngineBackend.py b/plugins/CuraEngineBackend/CuraEngineBackend.py index 4c0ed55bfe..ed4141c99a 100755 --- a/plugins/CuraEngineBackend/CuraEngineBackend.py +++ b/plugins/CuraEngineBackend/CuraEngineBackend.py @@ -937,6 +937,7 @@ class CuraEngineBackend(QObject, Backend): ) message.actionTriggered.connect(self._reportBackendError) message.show() + self.stopSlicing() else: Logger.log("d", "Backend finished slicing. Resetting process and socket.") self._process = None # type: ignore From 26a17e06038e94536efb1929e8c174f714ec0e66 Mon Sep 17 00:00:00 2001 From: Konstantinos Karmas Date: Thu, 15 Jul 2021 10:02:57 +0200 Subject: [PATCH 65/96] Code-style improvement CURA-8112 Co-authored-by: Ghostkeeper --- resources/qml/Cura.qml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/resources/qml/Cura.qml b/resources/qml/Cura.qml index e91dd39091..7782ace3af 100644 --- a/resources/qml/Cura.qml +++ b/resources/qml/Cura.qml @@ -436,7 +436,8 @@ UM.MainWindow Cura.TertiaryButton { text: model.name - iconSource: { + iconSource: + { if (model.icon == null || model.icon == "") { return UM.Theme.getIcon("LinkExternal") From d675386358f709f3a3517c26abd7c52112d09821 Mon Sep 17 00:00:00 2001 From: PurpleHullPeas <39073039+PurpleHullPeas@users.noreply.github.com> Date: Thu, 15 Jul 2021 07:44:24 -0500 Subject: [PATCH 66/96] Adding MP Mini Delta V2 Extruder --- .../mp_mini_delta_v2_extruder_0.def.json | 15 +++++++++++++++ 1 file changed, 15 insertions(+) create mode 100644 resources/extruders/mp_mini_delta_v2_extruder_0.def.json diff --git a/resources/extruders/mp_mini_delta_v2_extruder_0.def.json b/resources/extruders/mp_mini_delta_v2_extruder_0.def.json new file mode 100644 index 0000000000..022ace632f --- /dev/null +++ b/resources/extruders/mp_mini_delta_v2_extruder_0.def.json @@ -0,0 +1,15 @@ +{ + "version": 2, + "name": "Extruder 0", + "inherits": "fdmextruder", + "metadata": { + "machine": "mp_mini_delta_v2", + "position": "0" + }, + + "overrides": { + "extruder_nr": { "default_value": 0 }, + "machine_nozzle_size": { "default_value": 0.4 }, + "material_diameter": { "default_value": 1.75 } + } +} From 3f1052f756608d810ad0afa8fe28012dbc03f5d2 Mon Sep 17 00:00:00 2001 From: PurpleHullPeas <39073039+PurpleHullPeas@users.noreply.github.com> Date: Thu, 15 Jul 2021 07:47:00 -0500 Subject: [PATCH 67/96] Minor MP Mini Delta V1 Def updates Adding comment distinguishing the printer as the V1 versus the V2. Removing "+5" initial layer temperatures. Setting line width equal to nozzle size. --- resources/definitions/mp_mini_delta.def.json | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/resources/definitions/mp_mini_delta.def.json b/resources/definitions/mp_mini_delta.def.json index bbdca2c8f8..eda45bb413 100644 --- a/resources/definitions/mp_mini_delta.def.json +++ b/resources/definitions/mp_mini_delta.def.json @@ -3,7 +3,7 @@ "name": "MP Mini Delta", "inherits": "fdmprinter", "metadata": { - "author": "MPMD Facebook Group", + "author": "MPMD V1 Facebook Group", "manufacturer": "Monoprice", "file_formats": "text/x-gcode", "platform": "mp_mini_delta_platform.3mf", @@ -25,7 +25,7 @@ "overrides": { "machine_start_gcode": { - "default_value": ";MPMD Basic Calibration Tutorial: \n; https://www.thingiverse.com/thing:3892011 \n; \n; If you want to put calibration values in your \n; Start Gcode, put them here. \n; \n;If on stock firmware, at minimum, consider adding \n;M665 R here since there is a firmware bug. \n; \n; Calibration part ends here \n; \nG90 ; switch to absolute positioning \nG92 E0 ; reset extrusion distance \nG1 E20 F200 ; purge 20mm of filament to prime nozzle. \nG92 E0 ; reset extrusion distance \nG4 S5 ; Pause for 5 seconds to allow time for removing extruded filament \nG28 ; start from home position \nG1 E-6 F900 ; retract 6mm of filament before starting the bed leveling process \nG92 E0 ; reset extrusion distance \nG4 S5 ; pause for 5 seconds to allow time for removing extruded filament \nG29 P2 Z0.28 ; Auto-level ; ADJUST Z higher or lower to set first layer height. Start with 0.02 adjustments. \nG1 Z30 ; raise Z 30mm to prepare for priming the nozzle \nG1 E5 F200 ; extrude 5mm of filament to help prime the nozzle just prior to the start of the print \nG92 E0 ; reset extrusion distance \nG4 S5 ; pause for 5 seconds to allow time for cleaning the nozzle and build plate if needed " + "default_value": ";MPMD V1 Basic Calibration Tutorial: \n; https://www.thingiverse.com/thing:3892011 \n; \n; If you want to put calibration values in your \n; Start Gcode, put them here. \n; \n;If on stock firmware, at minimum, consider adding \n;M665 R here since there is a firmware bug. \n; \n; Calibration part ends here \n; \nG90 ; switch to absolute positioning \nG92 E0 ; reset extrusion distance \nG1 E20 F200 ; purge 20mm of filament to prime nozzle. \nG92 E0 ; reset extrusion distance \nG4 S5 ; Pause for 5 seconds to allow time for removing extruded filament \nG28 ; start from home position \nG1 E-6 F900 ; retract 6mm of filament before starting the bed leveling process \nG92 E0 ; reset extrusion distance \nG4 S5 ; pause for 5 seconds to allow time for removing extruded filament \nG29 P2 Z0.28 ; Auto-level ; ADJUST Z higher or lower to set first layer height. Start with 0.02 adjustments. \nG1 Z30 ; raise Z 30mm to prepare for priming the nozzle \nG1 E5 F200 ; extrude 5mm of filament to help prime the nozzle just prior to the start of the print \nG92 E0 ; reset extrusion distance \nG4 S5 ; pause for 5 seconds to allow time for cleaning the nozzle and build plate if needed " }, "machine_end_gcode": { @@ -47,9 +47,9 @@ "default_value": 0.21 }, "material_bed_temperature": { "value": 40 }, - "line_width": { "value": "round(machine_nozzle_size * 0.875, 2)" }, - "material_print_temperature_layer_0": { "value": "material_print_temperature + 5" }, - "material_bed_temperature_layer_0": { "value": "material_bed_temperature + 5" }, + "line_width": { "value": "round(machine_nozzle_size, 2)" }, + "material_print_temperature_layer_0": { "value": "material_print_temperature" }, + "material_bed_temperature_layer_0": { "value": "material_bed_temperature" }, "machine_gcode_flavor": { "default_value": "RepRap (Marlin/Sprinter)" }, "machine_max_feedrate_x": { "default_value": 150 }, "machine_max_feedrate_y": { "default_value": 150 }, From b20a1839225530e1bc8b4a8c347058df48708462 Mon Sep 17 00:00:00 2001 From: PurpleHullPeas <39073039+PurpleHullPeas@users.noreply.github.com> Date: Thu, 15 Jul 2021 07:48:02 -0500 Subject: [PATCH 68/96] Adding MP Mini Delta V2 def Utilizing information shared from MP Mini Delta V2 owners in order to make this definition work. --- .../definitions/mp_mini_delta_v2.def.json | 52 +++++++++++++++++++ 1 file changed, 52 insertions(+) create mode 100644 resources/definitions/mp_mini_delta_v2.def.json diff --git a/resources/definitions/mp_mini_delta_v2.def.json b/resources/definitions/mp_mini_delta_v2.def.json new file mode 100644 index 0000000000..0e3663eed9 --- /dev/null +++ b/resources/definitions/mp_mini_delta_v2.def.json @@ -0,0 +1,52 @@ +{ + "version": 3, + "name": "MP Mini Delta V2", + "inherits": "fdmprinter", + "metadata": { + "author": "r/mpminidelta", + "manufacturer": "Monoprice", + "file_formats": "text/x-gcode", + "platform": "mp_mini_delta_platform.3mf", + "supports_usb_connection": true, + "has_machine_quality": false, + "visible": true, + "platform_offset": [0, 0, 0], + "has_materials": true, + "has_variants": false, + "has_machine_materials": false, + "has_variant_materials": false, + "preferred_quality_type": "normal", + "machine_extruder_trains": + { + "0": "mp_mini_delta_v2_extruder_0" + } + }, + + "overrides": { + "machine_start_gcode": + { + "default_value": ";(**** start.gcode for MP Mini Delta V2****)\nG21\nG90\nM82\nM107\nM104 S170\nG28 X0 Y0\nG28 Z0\nG29 Z0.4\nG1 Z15 F300\nM109 S{material_print_temperature_layer_0}\nG92 E0\nG1 F200 E3\nG92 E0\nG1 F2000\n" + }, + "machine_end_gcode": { + "default_value": ";(**** end.gcode for MP Mini Delta****)\nG28;(Stick out the part)\nM190 S0;(Turn off heat bed, don't wait.)\nG92 E10;(Set extruder to 10)\nG1 E7 F200;(retract 3mm)\nM104 S0;(Turn off nozzle, don't wait)\nG4 S300;(Delay 5 minutes)\nM107;(Turn off part fan)\nM84;(Turn off stepper motors.)" + }, + "machine_width": { "default_value": 110 }, + "machine_depth": { "default_value": 110 }, + "machine_height": { "default_value": 120 }, + "machine_heated_bed": { "default_value": true }, + "machine_shape": { "default_value": "elliptic" }, + "machine_center_is_zero": { "default_value": true }, + "machine_nozzle_size": { + "default_value": 0.4 + }, + "material_bed_temperature": { "value": 40 }, + "line_width": { "value": "round(machine_nozzle_size, 2)" }, + "material_print_temperature_layer_0": { "value": "material_print_temperature" }, + "material_bed_temperature_layer_0": { "value": "material_bed_temperature" }, + "machine_gcode_flavor": { "default_value": "RepRap (Marlin/Sprinter)" }, + "retraction_amount": { "default_value": 5 }, + "retraction_speed": { "default_value": 28 }, + "retraction_hop_enabled": { "default_value": false }, + "retract_at_layer_change": { "default_value": true } + } +} From e9e9795bcc629b773d34974da247724412f1ba61 Mon Sep 17 00:00:00 2001 From: PurpleHullPeas <39073039+PurpleHullPeas@users.noreply.github.com> Date: Thu, 15 Jul 2021 08:16:46 -0500 Subject: [PATCH 69/96] MP Mini Delta V2 temperature settings and version. --- resources/definitions/mp_mini_delta_v2.def.json | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) diff --git a/resources/definitions/mp_mini_delta_v2.def.json b/resources/definitions/mp_mini_delta_v2.def.json index 0e3663eed9..64a5c2f0f2 100644 --- a/resources/definitions/mp_mini_delta_v2.def.json +++ b/resources/definitions/mp_mini_delta_v2.def.json @@ -1,9 +1,9 @@ { - "version": 3, + "version": 2, "name": "MP Mini Delta V2", "inherits": "fdmprinter", "metadata": { - "author": "r/mpminidelta", + "author": "mpminidelta subreddit", "manufacturer": "Monoprice", "file_formats": "text/x-gcode", "platform": "mp_mini_delta_platform.3mf", @@ -28,8 +28,15 @@ "default_value": ";(**** start.gcode for MP Mini Delta V2****)\nG21\nG90\nM82\nM107\nM104 S170\nG28 X0 Y0\nG28 Z0\nG29 Z0.4\nG1 Z15 F300\nM109 S{material_print_temperature_layer_0}\nG92 E0\nG1 F200 E3\nG92 E0\nG1 F2000\n" }, "machine_end_gcode": { - "default_value": ";(**** end.gcode for MP Mini Delta****)\nG28;(Stick out the part)\nM190 S0;(Turn off heat bed, don't wait.)\nG92 E10;(Set extruder to 10)\nG1 E7 F200;(retract 3mm)\nM104 S0;(Turn off nozzle, don't wait)\nG4 S300;(Delay 5 minutes)\nM107;(Turn off part fan)\nM84;(Turn off stepper motors.)" + "default_value": ";(**** end.gcode for MP Mini Delta V2****)\nG28;(Stick out the part)\nM190 S0;(Turn off heat bed, don't wait.)\nG92 E10;(Set extruder to 10)\nG1 E7 F200;(retract 3mm)\nM104 S0;(Turn off nozzle, don't wait)\nG4 S300;(Delay 5 minutes)\nM107;(Turn off part fan)\nM84;(Turn off stepper motors.)" }, + "material_print_temp_prepend":{"default_value":false}, + "default_material_bed_temperature":{ + "default_value": 40 + }, + "material_bed_temperature":{ + "default_value": 40 + }, "machine_width": { "default_value": 110 }, "machine_depth": { "default_value": 110 }, "machine_height": { "default_value": 120 }, @@ -39,10 +46,7 @@ "machine_nozzle_size": { "default_value": 0.4 }, - "material_bed_temperature": { "value": 40 }, "line_width": { "value": "round(machine_nozzle_size, 2)" }, - "material_print_temperature_layer_0": { "value": "material_print_temperature" }, - "material_bed_temperature_layer_0": { "value": "material_bed_temperature" }, "machine_gcode_flavor": { "default_value": "RepRap (Marlin/Sprinter)" }, "retraction_amount": { "default_value": 5 }, "retraction_speed": { "default_value": 28 }, From 983d1fc8a2c9a4f94145f3dcdefb6a2c437cdd2f Mon Sep 17 00:00:00 2001 From: PurpleHullPeas <39073039+PurpleHullPeas@users.noreply.github.com> Date: Thu, 15 Jul 2021 08:21:08 -0500 Subject: [PATCH 70/96] Removing mp_mini_delta_v2 default bed temperature. --- resources/definitions/mp_mini_delta_v2.def.json | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/resources/definitions/mp_mini_delta_v2.def.json b/resources/definitions/mp_mini_delta_v2.def.json index 64a5c2f0f2..30c7cb2823 100644 --- a/resources/definitions/mp_mini_delta_v2.def.json +++ b/resources/definitions/mp_mini_delta_v2.def.json @@ -31,12 +31,7 @@ "default_value": ";(**** end.gcode for MP Mini Delta V2****)\nG28;(Stick out the part)\nM190 S0;(Turn off heat bed, don't wait.)\nG92 E10;(Set extruder to 10)\nG1 E7 F200;(retract 3mm)\nM104 S0;(Turn off nozzle, don't wait)\nG4 S300;(Delay 5 minutes)\nM107;(Turn off part fan)\nM84;(Turn off stepper motors.)" }, "material_print_temp_prepend":{"default_value":false}, - "default_material_bed_temperature":{ - "default_value": 40 - }, - "material_bed_temperature":{ - "default_value": 40 - }, + "material_bed_temperature": { "value": 40 }, "machine_width": { "default_value": 110 }, "machine_depth": { "default_value": 110 }, "machine_height": { "default_value": 120 }, From 82c189327d9deae7fd7f0320ae76dc6ce668476a Mon Sep 17 00:00:00 2001 From: Konstantinos Karmas Date: Thu, 15 Jul 2021 16:36:49 +0200 Subject: [PATCH 71/96] Change link of "Upgrade plan" button CURA-8112 --- plugins/DigitalLibrary/resources/qml/SelectProjectPage.qml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/DigitalLibrary/resources/qml/SelectProjectPage.qml b/plugins/DigitalLibrary/resources/qml/SelectProjectPage.qml index 98b0c5ca02..2b0ca664cc 100644 --- a/plugins/DigitalLibrary/resources/qml/SelectProjectPage.qml +++ b/plugins/DigitalLibrary/resources/qml/SelectProjectPage.qml @@ -81,7 +81,7 @@ Item tooltip: "You have reached the maximum number of projects allowed by your subscription. Please upgrade to the Professional subscription to create more projects." tooltipWidth: parent.width * 0.5 - onClicked: Qt.openUrlExternally("https://ultimaker.com/software/enterprise-software") + onClicked: Qt.openUrlExternally("https://ultimaker.com/software/ultimaker-essentials/sign-up-cura?utm_source=cura&utm_medium=software&utm_campaign=lib-max") } } From e127f7e4b610903a8b98f4341314e91c3253e076 Mon Sep 17 00:00:00 2001 From: Ghostkeeper Date: Thu, 15 Jul 2021 16:45:50 +0200 Subject: [PATCH 72/96] Move construction of slicing error message to constructor This way we could re-use it in other places. Contributes to issue CURA-6568. --- .../CuraEngineBackend/CuraEngineBackend.py | 25 ++++++++++--------- 1 file changed, 13 insertions(+), 12 deletions(-) diff --git a/plugins/CuraEngineBackend/CuraEngineBackend.py b/plugins/CuraEngineBackend/CuraEngineBackend.py index ed4141c99a..d49baf189e 100755 --- a/plugins/CuraEngineBackend/CuraEngineBackend.py +++ b/plugins/CuraEngineBackend/CuraEngineBackend.py @@ -157,6 +157,18 @@ class CuraEngineBackend(QObject, Backend): self.determineAutoSlicing() application.getPreferences().preferenceChanged.connect(self._onPreferencesChanged) + self._slicing_error_message = Message( + text = catalog.i18nc("@message", "Slicing failed with an unexpected error. Please consider reporting a bug on our issue tracker."), + title = catalog.i18nc("@message:title", "Slicing failed") + ) + self._slicing_error_message.addAction( + action_id = "report_bug", + name = catalog.i18nc("@message:button", "Report a bug"), + description = catalog.i18nc("@message:description", "Report a bug on Ultimaker Cura's issue tracker."), + icon = "[no_icon]" + ) + self._slicing_error_message.actionTriggered.connect(self._reportBackendError) + self._snapshot = None #type: Optional[QImage] application.initializationFinished.connect(self.initialize) @@ -925,18 +937,7 @@ class CuraEngineBackend(QObject, Backend): return_code = self._process.wait() if return_code != 0: Logger.log("e", f"Backend exited abnormally with return code {return_code}!") - message = Message( - text = catalog.i18nc("@message", "Slicing failed with an unexpected error. Please consider reporting a bug on our issue tracker."), - title = catalog.i18nc("@message:title", "Slicing failed") - ) - message.addAction( - action_id = "report_bug", - name = catalog.i18nc("@message:button", "Report a bug"), - description = catalog.i18nc("@message:description", "Report a bug on Ultimaker Cura's issue tracker."), - icon = "[no_icon]" - ) - message.actionTriggered.connect(self._reportBackendError) - message.show() + self._slicing_error_message.show() self.stopSlicing() else: Logger.log("d", "Backend finished slicing. Resetting process and socket.") From 623b59d0e85190b0477c16f47295dfb44f81a879 Mon Sep 17 00:00:00 2001 From: Ghostkeeper Date: Thu, 15 Jul 2021 16:48:39 +0200 Subject: [PATCH 73/96] Set self to be in an error state if backend crashed Contributes to issue CURA-6568. --- plugins/CuraEngineBackend/CuraEngineBackend.py | 1 + 1 file changed, 1 insertion(+) diff --git a/plugins/CuraEngineBackend/CuraEngineBackend.py b/plugins/CuraEngineBackend/CuraEngineBackend.py index d49baf189e..fa9a8c5474 100755 --- a/plugins/CuraEngineBackend/CuraEngineBackend.py +++ b/plugins/CuraEngineBackend/CuraEngineBackend.py @@ -938,6 +938,7 @@ class CuraEngineBackend(QObject, Backend): if return_code != 0: Logger.log("e", f"Backend exited abnormally with return code {return_code}!") self._slicing_error_message.show() + self.setState(BackendState.Error) self.stopSlicing() else: Logger.log("d", "Backend finished slicing. Resetting process and socket.") From 40fe8b577d004d1357235e931ee7344b013d96ad Mon Sep 17 00:00:00 2001 From: Ghostkeeper Date: Thu, 15 Jul 2021 17:01:07 +0200 Subject: [PATCH 74/96] Also show error message if connection got reset without error code When working with --external-backend, the engine just stops responding, and the operating system cleans up its socket connection. From Cura's front-end we then just see the socket reset. So we should interpret a reset socket to mean that the slicing process was halted. When not working with an external backend, a crash would always give a response code and we can base it on that instead (as previously implemented). Contributes to issue CURA-6568. --- plugins/CuraEngineBackend/CuraEngineBackend.py | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/plugins/CuraEngineBackend/CuraEngineBackend.py b/plugins/CuraEngineBackend/CuraEngineBackend.py index fa9a8c5474..272ad3a7e9 100755 --- a/plugins/CuraEngineBackend/CuraEngineBackend.py +++ b/plugins/CuraEngineBackend/CuraEngineBackend.py @@ -610,10 +610,15 @@ class CuraEngineBackend(QObject, Backend): if error.getErrorCode() not in [Arcus.ErrorCode.BindFailedError, Arcus.ErrorCode.ConnectionResetError, Arcus.ErrorCode.Debug]: Logger.log("w", "A socket error caused the connection to be reset") + elif error.getErrorCode() == Arcus.ErrorCode.ConnectionResetError: + Logger.error("CuraEngine crashed abnormally! The socket connection was reset unexpectedly.") + self._slicing_error_message.show() + self.setState(BackendState.Error) + self.stopSlicing() # _terminate()' function sets the job status to 'cancel', after reconnecting to another Port the job status # needs to be updated. Otherwise backendState is "Unable To Slice" - if error.getErrorCode() == Arcus.ErrorCode.BindFailedError and self._start_slice_job is not None: + elif error.getErrorCode() == Arcus.ErrorCode.BindFailedError and self._start_slice_job is not None: self._start_slice_job.setIsCancelled(False) # Check if there's any slicable object in the scene. From 5503c576312454eff1b7427c9444fc032235e31f Mon Sep 17 00:00:00 2001 From: Ghostkeeper Date: Thu, 15 Jul 2021 18:24:25 +0200 Subject: [PATCH 75/96] Reduce margins around troubleshooting link This makes the link space out better on some screens, where the space is limited. Contributes to issue CURA-8392. --- .../qml/WelcomePages/AddNetworkPrinterScrollView.qml | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/resources/qml/WelcomePages/AddNetworkPrinterScrollView.qml b/resources/qml/WelcomePages/AddNetworkPrinterScrollView.qml index 5334a15974..58cadbec37 100644 --- a/resources/qml/WelcomePages/AddNetworkPrinterScrollView.qml +++ b/resources/qml/WelcomePages/AddNetworkPrinterScrollView.qml @@ -1,4 +1,4 @@ -// Copyright (c) 2019 Ultimaker B.V. +// Copyright (c) 2021 Ultimaker B.V. // Cura is released under the terms of the LGPLv3 or higher. import QtQuick 2.10 @@ -214,16 +214,16 @@ Item id: troubleshootingButton anchors.right: parent.right - anchors.rightMargin: UM.Theme.getSize("default_margin").width + anchors.rightMargin: UM.Theme.getSize("thin_margin").width anchors.verticalCenter: parent.verticalCenter height: troubleshootingLinkIcon.height - width: troubleshootingLinkIcon.width + troubleshootingLabel.width + UM.Theme.getSize("default_margin").width + width: troubleshootingLinkIcon.width + troubleshootingLabel.width + UM.Theme.getSize("thin_margin").width UM.RecolorImage { id: troubleshootingLinkIcon anchors.right: troubleshootingLabel.left - anchors.rightMargin: UM.Theme.getSize("default_margin").width + anchors.rightMargin: UM.Theme.getSize("thin_margin").width anchors.verticalCenter: parent.verticalCenter height: troubleshootingLabel.height width: height From 6f6d8d0f93927a202d81100cc203364f0aa01314 Mon Sep 17 00:00:00 2001 From: Ghostkeeper Date: Thu, 15 Jul 2021 18:46:20 +0200 Subject: [PATCH 76/96] Override all settings that might influence infill mesh shells to 0 If the user had specialised settings fixing the number of walls or skin layers to an integer number, this fixed value would get copied over from the extruder settings, causing infill meshes to have walls by default. This is unintuitive. We want infill meshes to behave like it's only infill by default. So remove all of those overrides so that only infill gets printed there, by default. The user may still change the number of walls or skin layers or their parent settings. But by default it should now behave like infill within infill, regardless of the user's setting overrides. Fixes issue CURA-8393 and fixes #9815. --- .../PerObjectSettingsTool.py | 21 ++++++++++++------- 1 file changed, 14 insertions(+), 7 deletions(-) diff --git a/plugins/PerObjectSettingsTool/PerObjectSettingsTool.py b/plugins/PerObjectSettingsTool/PerObjectSettingsTool.py index ab2bcaad5b..e80acc8d94 100644 --- a/plugins/PerObjectSettingsTool/PerObjectSettingsTool.py +++ b/plugins/PerObjectSettingsTool/PerObjectSettingsTool.py @@ -1,4 +1,4 @@ -# Copyright (c) 2020 Ultimaker B.V. +# Copyright (c) 2021 Ultimaker B.V. # Cura is released under the terms of the LGPLv3 or higher. from UM.Logger import Logger @@ -103,20 +103,27 @@ class PerObjectSettingsTool(Tool): new_instance.resetState() # Ensure that the state is not seen as a user state. settings.addInstance(new_instance) - for property_key in ["top_bottom_thickness", "wall_thickness", "wall_line_count"]: + # Override some settings to ensure that the infill mesh by default adds no skin or walls. Or remove them if not an infill mesh. + specialized_settings = { + "top_bottom_thickness": 0, + "top_thickness": "=top_bottom_thickness", + "bottom_thickness": "=top_bottom_thickness", + "top_layers": "=0 if infill_sparse_density == 100 else math.ceil(round(top_thickness / resolveOrValue('layer_height'), 4))", + "bottom_layers": "=0 if infill_sparse_density == 100 else math.ceil(round(bottom_thickness / resolveOrValue('layer_height'), 4))", + "wall_thickness": 0, + "wall_line_count": "=max(1, round((wall_thickness - wall_line_width_0) / wall_line_width_x) + 1) if wall_thickness != 0 else 0" + } + for property_key in specialized_settings: if mesh_type == "infill_mesh": if settings.getInstance(property_key) is None: definition = stack.getSettingDefinition(property_key) new_instance = SettingInstance(definition, settings) - # We just want the wall_line count to be there in case it was overriden in the global stack. - # as such, we don't need to set a value. - if property_key != "wall_line_count": - new_instance.setProperty("value", 0) + new_instance.setProperty("value", specialized_settings[property_key]) new_instance.resetState() # Ensure that the state is not seen as a user state. settings.addInstance(new_instance) settings_visibility_changed = True - elif old_mesh_type == "infill_mesh" and settings.getInstance(property_key) and (settings.getProperty(property_key, "value") == 0 or property_key == "wall_line_count"): + elif old_mesh_type == "infill_mesh" and settings.getInstance(property_key) and property_key in specialized_settings: settings.removeInstance(property_key) settings_visibility_changed = True From 65a2cd30fe0ee6116efba818f467e1a2551c2ace Mon Sep 17 00:00:00 2001 From: Ghostkeeper Date: Fri, 16 Jul 2021 09:48:40 +0200 Subject: [PATCH 77/96] Corrections to the paths to log files These have been wrong for years, I reckon... --- README.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index ff39e4142a..345a55d12f 100644 --- a/README.md +++ b/README.md @@ -10,9 +10,9 @@ For crashes and similar issues, please attach the following information: * (On Windows) The log as produced by dxdiag (start -> run -> dxdiag -> save output) * The Cura GUI log file, located at - * `%APPDATA%\cura\\cura.log` (Windows), or usually `C:\Users\\\AppData\Roaming\cura\\cura.log` - * `$USER/Library/Application Support/cura//cura.log` (OSX) - * `$USER/.local/share/cura//cura.log` (Ubuntu/Linux) + * `%APPDATA%\cura\\cura.log` (Windows), or usually `C:\Users\\AppData\Roaming\cura\\cura.log` + * `$HOME/Library/Application Support/cura//cura.log` (OSX) + * `$HOME/.local/share/cura//cura.log` (Ubuntu/Linux) If the Cura user interface still starts, you can also reach this directory from the application menu in Help -> Show settings folder From 503293fbebd3ee0c1c1481287c4a005a951d6d27 Mon Sep 17 00:00:00 2001 From: Ghostkeeper Date: Fri, 16 Jul 2021 10:15:40 +0200 Subject: [PATCH 78/96] Revert "Also show error message if connection got reset without error code" This reverts commit 40fe8b577d004d1357235e931ee7344b013d96ad. --- plugins/CuraEngineBackend/CuraEngineBackend.py | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/plugins/CuraEngineBackend/CuraEngineBackend.py b/plugins/CuraEngineBackend/CuraEngineBackend.py index 272ad3a7e9..fa9a8c5474 100755 --- a/plugins/CuraEngineBackend/CuraEngineBackend.py +++ b/plugins/CuraEngineBackend/CuraEngineBackend.py @@ -610,15 +610,10 @@ class CuraEngineBackend(QObject, Backend): if error.getErrorCode() not in [Arcus.ErrorCode.BindFailedError, Arcus.ErrorCode.ConnectionResetError, Arcus.ErrorCode.Debug]: Logger.log("w", "A socket error caused the connection to be reset") - elif error.getErrorCode() == Arcus.ErrorCode.ConnectionResetError: - Logger.error("CuraEngine crashed abnormally! The socket connection was reset unexpectedly.") - self._slicing_error_message.show() - self.setState(BackendState.Error) - self.stopSlicing() # _terminate()' function sets the job status to 'cancel', after reconnecting to another Port the job status # needs to be updated. Otherwise backendState is "Unable To Slice" - elif error.getErrorCode() == Arcus.ErrorCode.BindFailedError and self._start_slice_job is not None: + if error.getErrorCode() == Arcus.ErrorCode.BindFailedError and self._start_slice_job is not None: self._start_slice_job.setIsCancelled(False) # Check if there's any slicable object in the scene. From c2f23045122b112902239ccf12be9c73a3015569 Mon Sep 17 00:00:00 2001 From: Ghostkeeper Date: Fri, 16 Jul 2021 10:48:24 +0200 Subject: [PATCH 79/96] Move Kossel Pro platform mesh a bit lower to prevent Z-fighting As reported in #8296. --- resources/definitions/anycubic_kossel_linear_plus.def.json | 1 + 1 file changed, 1 insertion(+) diff --git a/resources/definitions/anycubic_kossel_linear_plus.def.json b/resources/definitions/anycubic_kossel_linear_plus.def.json index a4aeac75a0..9683cf61cf 100644 --- a/resources/definitions/anycubic_kossel_linear_plus.def.json +++ b/resources/definitions/anycubic_kossel_linear_plus.def.json @@ -5,6 +5,7 @@ "metadata": { "visible": true, "platform": "kossel_pro_build_platform.3mf", + "platform_offset": [0, -0.25, 0], "machine_extruder_trains": { "0": "anycubic_kossel_extruder_0" } From f9557295fa3fa329260856ed790af86668274b11 Mon Sep 17 00:00:00 2001 From: Remco Burema Date: Fri, 16 Jul 2021 12:39:41 +0200 Subject: [PATCH 80/96] Allow non-ASCII characters for DL project names. CURA-8395 --- plugins/DigitalLibrary/src/DigitalFactoryApiClient.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/DigitalLibrary/src/DigitalFactoryApiClient.py b/plugins/DigitalLibrary/src/DigitalFactoryApiClient.py index 9a3157ccd6..a9a1ab360b 100644 --- a/plugins/DigitalLibrary/src/DigitalFactoryApiClient.py +++ b/plugins/DigitalLibrary/src/DigitalFactoryApiClient.py @@ -366,7 +366,7 @@ class DigitalFactoryApiClient: :param on_error: The function to be called if anything goes wrong. """ - display_name = re.sub(r"[^a-zA-Z0-9- ./™®ö+']", " ", project_name) + display_name = re.sub(r"^[\\w\\-\\. ()]+\\.[a-zA-Z0-9]+$", " ", project_name) Logger.log("i", "Attempt to create new DF project '{}'.".format(display_name)) url = "{}/projects".format(self.CURA_API_ROOT) From c60295c69ee41a599b5a25f78cac8479d2d1e729 Mon Sep 17 00:00:00 2001 From: Thushan Fernando Date: Fri, 16 Jul 2021 21:43:22 +1000 Subject: [PATCH 81/96] Adds FLSun Super Racer Profile (#10078) * Initial FLSun Super Racer profile setup. * flip has_machine_quality to false as suggested by @konskarm. * tabs vs spaces! Space is the final frontier! * Enumeration value should be in inner single quotes as requested by @konskarm. --- resources/definitions/flsun_sr.def.json | 76 ++++++++++++++++++ .../extruders/flsun_sr_extruder_0.def.json | 20 +++++ resources/meshes/flsun_sr.3mf | Bin 0 -> 226011 bytes 3 files changed, 96 insertions(+) create mode 100644 resources/definitions/flsun_sr.def.json create mode 100644 resources/extruders/flsun_sr_extruder_0.def.json create mode 100644 resources/meshes/flsun_sr.3mf diff --git a/resources/definitions/flsun_sr.def.json b/resources/definitions/flsun_sr.def.json new file mode 100644 index 0000000000..6ca839198e --- /dev/null +++ b/resources/definitions/flsun_sr.def.json @@ -0,0 +1,76 @@ +{ + "version": 2, + "name": "FlSun SuperRacer", + "inherits": "fdmprinter", + "metadata": { + "visible": true, + "author": "Thushan Fernando", + "manufacturer": "Flsun", + "platform": "flsun_sr.3mf", + "file_formats": "text/x-gcode", + "has_materials": true, + "has_machine_quality": false, + "preferred_quality_type": "fast", + "machine_extruder_trains": { + "0": "flsun_sr_extruder_0" + } + }, + "overrides": { + "machine_extruder_count": { + "default_value": 1 + }, + "retraction_enable": { + "default_value": true + }, + "machine_heated_bed": { + "default_value": true + }, + "machine_width": { + "default_value": 260 + }, + "machine_depth": { + "default_value": 260 + }, + "machine_height": { + "default_value": 330 + }, + "machine_center_is_zero": { + "default_value": true + }, + "machine_head_with_fans_polygon": { + "default_value": [ + [0, 0], + [0, 0], + [0, 0], + [0, 0] + ] + }, + "z_seam_type": { + "default_value": "'back'" + }, + "gantry_height": { + "value": "0" + }, + "machine_shape": { + "default_value": "elliptic" + }, + "machine_nozzle_size": { + "default_value": 0.4 + }, + "material_diameter": { + "default_value": 1.75 + }, + "infill_sparse_density": { + "default_value": 15 + }, + "machine_start_gcode": { + "default_value": "G21\nG90\nM82\nM107 T0\nM140 S{material_bed_temperature}\nM104 S{material_print_temperature} T0\nM190 S{material_bed_temperature}\nM109 S{material_print_temperature} T0\nG28\nG92 E0\n" + }, + "machine_end_gcode": { + "default_value": "M107 T0\nM104 S0\nM104 S0 T1\nM140 S0\nG92 E0\nG91\nG1 E-1 F300 \nG1 Z+0.5 E-5 F6000\nG28 X0 Y0\nG90 ;absolute positioning\n" + }, + "machine_gcode_flavor": { + "default_value": "RepRap (Marlin/Sprinter)" + } + } +} diff --git a/resources/extruders/flsun_sr_extruder_0.def.json b/resources/extruders/flsun_sr_extruder_0.def.json new file mode 100644 index 0000000000..31880b5130 --- /dev/null +++ b/resources/extruders/flsun_sr_extruder_0.def.json @@ -0,0 +1,20 @@ +{ + "version": 2, + "name": "Extruder 1", + "inherits": "fdmextruder", + "metadata": { + "machine": "flsun_sr", + "position": "0" + }, + "overrides": { + "extruder_nr": { + "default_value": 0 + }, + "machine_nozzle_size": { + "default_value": 0.4 + }, + "material_diameter": { + "default_value": 1.75 + } + } +} diff --git a/resources/meshes/flsun_sr.3mf b/resources/meshes/flsun_sr.3mf new file mode 100644 index 0000000000000000000000000000000000000000..7eba390a6692780f019272081094915a4697ad26 GIT binary patch literal 226011 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 z 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 literal 0 HcmV?d00001 From 5bd9970a82ea48ce94c17585f09c1c2a751d7f2e Mon Sep 17 00:00:00 2001 From: Konstantinos Karmas Date: Fri, 16 Jul 2021 13:44:14 +0200 Subject: [PATCH 82/96] Change default_value to value --- resources/definitions/flsun_sr.def.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/resources/definitions/flsun_sr.def.json b/resources/definitions/flsun_sr.def.json index 6ca839198e..9f68c129bd 100644 --- a/resources/definitions/flsun_sr.def.json +++ b/resources/definitions/flsun_sr.def.json @@ -46,7 +46,7 @@ ] }, "z_seam_type": { - "default_value": "'back'" + "value": "'back'" }, "gantry_height": { "value": "0" From 7ace87527907a3da1102b39d8794105da6780fda Mon Sep 17 00:00:00 2001 From: Jaime van Kessel Date: Mon, 19 Jul 2021 15:47:38 +0200 Subject: [PATCH 83/96] Also search on description when using search in visibility page --- resources/qml/Preferences/SettingVisibilityPage.qml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/resources/qml/Preferences/SettingVisibilityPage.qml b/resources/qml/Preferences/SettingVisibilityPage.qml index 37149c0009..d2fd5c7e94 100644 --- a/resources/qml/Preferences/SettingVisibilityPage.qml +++ b/resources/qml/Preferences/SettingVisibilityPage.qml @@ -95,7 +95,7 @@ UM.PreferencesPage placeholderText: catalog.i18nc("@label:textbox", "Filter...") - onTextChanged: definitionsModel.filter = {"i18n_label": "*" + text} + onTextChanged: definitionsModel.filter = {"i18n_label|i18n_description": "*" + text} } NewControls.ComboBox From 918d1f188b2094520e8f99a0b2507a5f21723e2c Mon Sep 17 00:00:00 2001 From: Luke Harrison Date: Mon, 19 Jul 2021 15:57:30 +0200 Subject: [PATCH 84/96] Biqu bx definition (#10086) * Added prelim support for the BX * Revert "Added prelim support for the BX" This reverts commit 923fbdbbb617d000663f04d08d468ed0c560517c. * Added prelim support for the BX * Revert "Added prelim support for the BX" This reverts commit 923fbdbbb617d000663f04d08d468ed0c560517c. * Added BIQU BX printer def * Updated the platform name. * Minor update to the start code. Ready for merge. --- resources/definitions/biqu_base.def.json | 6 +-- resources/definitions/biqu_bx_abl.def.json | 51 ++++++++++++++++++++ resources/meshes/BIQU_BX_PLATE.stl | Bin 0 -> 145584 bytes resources/variants/biqu_bx_abl_0.2.inst.cfg | 12 +++++ resources/variants/biqu_bx_abl_0.3.inst.cfg | 12 +++++ resources/variants/biqu_bx_abl_0.4.inst.cfg | 12 +++++ resources/variants/biqu_bx_abl_0.5.inst.cfg | 12 +++++ resources/variants/biqu_bx_abl_0.6.inst.cfg | 12 +++++ resources/variants/biqu_bx_abl_0.8.inst.cfg | 12 +++++ 9 files changed, 126 insertions(+), 3 deletions(-) create mode 100755 resources/definitions/biqu_bx_abl.def.json create mode 100644 resources/meshes/BIQU_BX_PLATE.stl create mode 100755 resources/variants/biqu_bx_abl_0.2.inst.cfg create mode 100755 resources/variants/biqu_bx_abl_0.3.inst.cfg create mode 100755 resources/variants/biqu_bx_abl_0.4.inst.cfg create mode 100755 resources/variants/biqu_bx_abl_0.5.inst.cfg create mode 100755 resources/variants/biqu_bx_abl_0.6.inst.cfg create mode 100755 resources/variants/biqu_bx_abl_0.8.inst.cfg diff --git a/resources/definitions/biqu_base.def.json b/resources/definitions/biqu_base.def.json index af5c2465e2..29aa69ec54 100755 --- a/resources/definitions/biqu_base.def.json +++ b/resources/definitions/biqu_base.def.json @@ -85,8 +85,8 @@ "material_flow": { "value": 100 }, "travel_compensate_overlapping_walls_0_enabled": { "value": "False" }, - "z_seam_type": { "value": "'back'" }, - "z_seam_corner": { "value": "'z_seam_corner_weighted'" }, + "z_seam_type": { "value": "'sharpest_corner'" }, + "z_seam_corner": { "value": "'z_seam_corner_inner'" }, "infill_line_width": { "value": "line_width * 1.2" }, "infill_sparse_density": { "value": "20" }, @@ -156,7 +156,7 @@ "support_interface_enable": { "value": true }, "support_interface_height": { "value": "layer_height * 4" }, - "support_interface_density": { "value": 33.333 }, + "support_interface_density": { "value": 75 }, "support_interface_pattern": { "value": "'grid'" }, "support_interface_skip_height": { "value": 0.2 }, "minimum_support_area": { "value": 2 }, diff --git a/resources/definitions/biqu_bx_abl.def.json b/resources/definitions/biqu_bx_abl.def.json new file mode 100755 index 0000000000..af4f50dec0 --- /dev/null +++ b/resources/definitions/biqu_bx_abl.def.json @@ -0,0 +1,51 @@ +{ + "name": "Biqu BX", + "version": 2, + "inherits": "biqu_base", + "metadata": { + "quality_definition": "biqu_base", + "visible": true, + "has_machine_materials": true, + "platform": "BIQU_BX_PLATE.stl", + "platform_offset": [ + 7, + -7.4, + -3 + ] + }, + "overrides": { + "coasting_enable": { "value": false }, + "retraction_amount": { "value": 1 }, + "retraction_speed": { "value": 40 }, + "retraction_extrusion_window": { "value": 1 }, + "retract_at_layer_change": { "value": true }, + "support_enable": { "value": false }, + "support_structure": { "value": "'normal'" }, + "support_type": { "value": "'buildplate'" }, + "support_angle": { "value": 45 }, + "support_infill_rate": { "value": 15 }, + "infill_overlap": { "value": 15.0 }, + "skin_overlap": { "value": 20.0 }, + "fill_outline_gaps": { "value": true }, + "filter_out_tiny_gaps": { "value": true }, + "roofing_layer_count": { "value": 2 }, + "xy_offset_layer_0": { "value": -0.1 }, + "speed_print": { "value": 50 }, + "machine_name": { "default_value": "Biqu BX" }, + "machine_width": { "value": 250 }, + "machine_depth": { "value": 250 }, + "machine_height": { "value": 250 }, + "machine_head_with_fans_polygon": { "default_value": [ + [-33, 35], + [-33, -23], + [33, -23], + [33, 35] + ] + }, + "machine_start_gcode": { + "default_value": "; BIQU BX Start G-code\r\n; For inforation on how to tune this profile and get the\r\n; most out of your BX visit: https:\/\/github.com\/looxonline\/Marlin\r\n; For the official github site visit: https:\/\/github.com\/bigtreetech\/BIQU-BX\r\n\r\nM117 Initial homing sequence. ; Home so that the probe is positioned to heat\r\nG28\r\n\r\nM117 Probe heating position\r\nG0 X65 Y5 Z1 ; Move the probe to the heating position.\r\n\r\nM117 Getting the heaters up to temp!\r\nM104 S140 ; Set Extruder temperature, no wait\r\nM140 S60 ; Set Heat Bed temperature\r\nM190 S60 ; Wait for Heat Bed temperature\r\n\r\nM117 Waiting for probe to warm! ; Wait another 90s for the probe to absorb heat.\r\nG4 S90 \r\n\r\nM117 Post warming re-home\r\nG28 ; Home all axes again after warming\r\n\r\nM117 Z-Dance of my people\r\nG34\r\n\r\nM117 ABL Probing\r\nG29\r\n\r\nM900 K0 L0 T0 ;Edit the K and L values if you have calibrated a k factor for your filament\r\nM900 T0 S0\r\n\r\nG1 Z2.0 F3000 ; Move Z Axis up little to prevent scratching of Heat Bed\r\nG1 X4.1 Y10 Z0.3 F5000.0 ; Move to start position\r\n\r\nM117 Getting the extruder up to temp\r\nM140 S{material_bed_temperature_layer_0} ; Set Heat Bed temperature\r\nM104 S{material_print_temperature_layer_0} ; Set Extruder temperature\r\nM109 S{material_print_temperature_layer_0} ; Wait for Extruder temperature\r\nM190 S{material_bed_temperature_layer_0} ; Wait for Heat Bed temperature\r\n\r\nG92 E0 ; Reset Extruder\r\nM117 Purging\r\nG1 X4.1 Y200.0 Z0.3 F1500.0 E15 ; Draw the first line\r\nG1 X4.4 Y200.0 Z0.3 F5000.0 ; Move to side a little\r\nG1 X4.4 Y20 Z0.3 F1500.0 E30 ; Draw the second line\r\nG92 E0 ; Reset Extruder\r\nM117 Lets make\r\nG1 X8 Y20 Z0.3 F5000.0 ; Move over to prevent blob squish" + }, + + "gantry_height": { "value": 27.5 } + } +} diff --git a/resources/meshes/BIQU_BX_PLATE.stl b/resources/meshes/BIQU_BX_PLATE.stl new file mode 100644 index 0000000000000000000000000000000000000000..9c1726f2765d74d27555c2429d38e22c3dbbb771 GIT binary patch literal 145584 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

m!TAsB=CKNN2az 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 PaI>nYX9&tb*v|cb Date: Mon, 19 Jul 2021 17:34:44 +0200 Subject: [PATCH 85/96] Don't translate certain keywords in the application menu on MacOS There's a suspicion that this is causing a crash on exit. From the traceback it seems like it's attempting to find a certain property on a deleted item. I'm thinking it might be trying to update properties on an item that was already deleted by the system here because the item got moved to a system-specific menu. Qt doesn't realise that. By not translating that property, it's not necessary to update and hopefully this prevents the need to look up data on the deleted item. Not translating it is not an issue anyway, since the menu will also be renamed by Qt to some system-specific name, which is then also translated to the user's system-language by MacOS itself. It's not at all sure if this will fix it. Tests are necessary. Contributes to issue CURA-8245. --- resources/qml/Actions.qml | 22 +++++++++++++++--- resources/qml/MainWindow/ApplicationMenu.qml | 24 +++++++++++++++++--- 2 files changed, 40 insertions(+), 6 deletions(-) diff --git a/resources/qml/Actions.qml b/resources/qml/Actions.qml index 7a4a837c66..bb9adc5b9f 100644 --- a/resources/qml/Actions.qml +++ b/resources/qml/Actions.qml @@ -1,4 +1,4 @@ -// Copyright (c) 2018 Ultimaker B.V. +// Copyright (c) 2021 Ultimaker B.V. // Cura is released under the terms of the LGPLv3 or higher. pragma Singleton @@ -122,7 +122,15 @@ Item Action { id: quitAction - text: catalog.i18nc("@action:inmenu menubar:file","&Quit") + + //On MacOS, don't translate the "Quit" word. + //Qt moves the "quit" entry to a different place, and if it got renamed can't find it again when it attempts to + //delete the item upon closing the application, causing a crash. + //In the new location, these items are translated automatically according to the system's language. + //For more information, see: + //- https://doc.qt.io/qt-5/macos-issues.html#menu-bar + //- https://doc.qt.io/qt-5/qmenubar.html#qmenubar-as-a-global-menu-bar + text: (Qt.platform.os == "osx") ? "&Quit" : catalog.i18nc("@action:inmenu menubar:file", "&Quit") iconName: "application-exit" shortcut: StandardKey.Quit } @@ -263,7 +271,15 @@ Item Action { id: aboutAction; - text: catalog.i18nc("@action:inmenu menubar:help", "About..."); + + //On MacOS, don't translate the "About" word. + //Qt moves the "about" entry to a different place, and if it got renamed can't find it again when it + //attempts to delete the item upon closing the application, causing a crash. + //In the new location, these items are translated automatically according to the system's language. + //For more information, see: + //- https://doc.qt.io/qt-5/macos-issues.html#menu-bar + //- https://doc.qt.io/qt-5/qmenubar.html#qmenubar-as-a-global-menu-bar + text: (Qt.platform.os == "osx") ? "About..." : catalog.i18nc("@action:inmenu menubar:help", "About..."); iconName: "help-about"; } diff --git a/resources/qml/MainWindow/ApplicationMenu.qml b/resources/qml/MainWindow/ApplicationMenu.qml index 95cea77248..50fe95bddb 100644 --- a/resources/qml/MainWindow/ApplicationMenu.qml +++ b/resources/qml/MainWindow/ApplicationMenu.qml @@ -1,4 +1,4 @@ -// Copyright (c) 2018 Ultimaker B.V. +// Copyright (c) 2021 Ultimaker B.V. // Cura is released under the terms of the LGPLv3 or higher. import QtQuick 2.7 @@ -48,7 +48,17 @@ Item ViewMenu { title: catalog.i18nc("@title:menu menubar:toplevel", "&View") } - SettingsMenu { title: catalog.i18nc("@title:menu menubar:toplevel", "&Settings") } + SettingsMenu + { + //On MacOS, don't translate the "Settings" word. + //Qt moves the "settings" entry to a different place, and if it got renamed can't find it again when it + //attempts to delete the item upon closing the application, causing a crash. + //In the new location, these items are translated automatically according to the system's language. + //For more information, see: + //- https://doc.qt.io/qt-5/macos-issues.html#menu-bar + //- https://doc.qt.io/qt-5/qmenubar.html#qmenubar-as-a-global-menu-bar + title: (Qt.platform.os == "osx") ? "&Settings" : catalog.i18nc("@title:menu menubar:toplevel", "&Settings") + } Menu { @@ -91,7 +101,15 @@ Item Menu { id: preferencesMenu - title: catalog.i18nc("@title:menu menubar:toplevel", "P&references") + + //On MacOS, don't translate the "Preferences" word. + //Qt moves the "preferences" entry to a different place, and if it got renamed can't find it again when it + //attempts to delete the item upon closing the application, causing a crash. + //In the new location, these items are translated automatically according to the system's language. + //For more information, see: + //- https://doc.qt.io/qt-5/macos-issues.html#menu-bar + //- https://doc.qt.io/qt-5/qmenubar.html#qmenubar-as-a-global-menu-bar + title: (Qt.platform.os == "osx") ? "P&references" : catalog.i18nc("@title:menu menubar:toplevel", "P&references") MenuItem { action: Cura.Actions.preferences } } From d536dd12a08a9fdffc78fe9c1530dfaa5e7f9d9d Mon Sep 17 00:00:00 2001 From: NilsRo <51311453+NilsRo@users.noreply.github.com> Date: Tue, 20 Jul 2021 09:11:32 +0200 Subject: [PATCH 86/96] Changed "Deviation" for Anycubic Mega S and X to better support hardware (#10093) * Update anycubic_i3_mega_s.def.json Adapted Deviation to ATMega2560 of Anycubic Mega S * Update resources/definitions/anycubic_i3_mega_s.def.json Good points. Thanks! Co-authored-by: Konstantinos Karmas Co-authored-by: Konstantinos Karmas --- resources/definitions/anycubic_i3_mega_s.def.json | 1 + 1 file changed, 1 insertion(+) diff --git a/resources/definitions/anycubic_i3_mega_s.def.json b/resources/definitions/anycubic_i3_mega_s.def.json index f0c786a393..a0e83627c4 100644 --- a/resources/definitions/anycubic_i3_mega_s.def.json +++ b/resources/definitions/anycubic_i3_mega_s.def.json @@ -115,6 +115,7 @@ "skirt_gap": { "value": 5.0 }, "skirt_line_count": { "value": 4 }, + "meshfix_maximum_deviation": { "value": 0.05 }, "support_angle": { "value": "math.floor(math.degrees(math.atan(line_width / 2.0 / layer_height)))" }, "support_pattern": { "value": "'zigzag'" }, From 109fce5211ac0edd3c02abc9d6345093651d0ec3 Mon Sep 17 00:00:00 2001 From: Ghostkeeper Date: Tue, 20 Jul 2021 15:22:44 +0200 Subject: [PATCH 87/96] Theoretical fix for MacOS not moving Preferences option any more Perhaps this ampersand was messing with it. Contributes to issue CURA-8245. --- resources/qml/MainWindow/ApplicationMenu.qml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/resources/qml/MainWindow/ApplicationMenu.qml b/resources/qml/MainWindow/ApplicationMenu.qml index 50fe95bddb..62b3a71ee8 100644 --- a/resources/qml/MainWindow/ApplicationMenu.qml +++ b/resources/qml/MainWindow/ApplicationMenu.qml @@ -109,7 +109,7 @@ Item //For more information, see: //- https://doc.qt.io/qt-5/macos-issues.html#menu-bar //- https://doc.qt.io/qt-5/qmenubar.html#qmenubar-as-a-global-menu-bar - title: (Qt.platform.os == "osx") ? "P&references" : catalog.i18nc("@title:menu menubar:toplevel", "P&references") + title: (Qt.platform.os == "osx") ? "&Preferences" : catalog.i18nc("@title:menu menubar:toplevel", "P&references") MenuItem { action: Cura.Actions.preferences } } From 71937bf828f3e20fde7cf70658cc8fe66ec15d14 Mon Sep 17 00:00:00 2001 From: Remco Burema Date: Tue, 20 Jul 2021 17:58:29 +0200 Subject: [PATCH 88/96] DL: Align with online backend on allowed characters. CURA-8395 --- .../DigitalLibrary/resources/qml/CreateNewProjectPopup.qml | 4 ++-- .../DigitalLibrary/resources/qml/SaveProjectFilesPage.qml | 4 ++-- plugins/DigitalLibrary/src/DigitalFactoryApiClient.py | 6 ++---- 3 files changed, 6 insertions(+), 8 deletions(-) diff --git a/plugins/DigitalLibrary/resources/qml/CreateNewProjectPopup.qml b/plugins/DigitalLibrary/resources/qml/CreateNewProjectPopup.qml index 75fb8d5811..a7297c12fb 100644 --- a/plugins/DigitalLibrary/resources/qml/CreateNewProjectPopup.qml +++ b/plugins/DigitalLibrary/resources/qml/CreateNewProjectPopup.qml @@ -93,7 +93,7 @@ Popup } validator: RegExpValidator { - regExp: /^[^\\\/\*\?\|\[\]]{0,96}$/ + regExp: /^[^\\\/\*\?\|\[\]]{0,99}$/ } text: PrintInformation.jobName @@ -148,7 +148,7 @@ Popup anchors.bottom: parent.bottom anchors.right: parent.right text: "Create" - enabled: newProjectNameTextField.text != "" && !busy + enabled: newProjectNameTextField.text.length >= 2 && !busy onClicked: { diff --git a/plugins/DigitalLibrary/resources/qml/SaveProjectFilesPage.qml b/plugins/DigitalLibrary/resources/qml/SaveProjectFilesPage.qml index 03bd655957..6b9361a900 100644 --- a/plugins/DigitalLibrary/resources/qml/SaveProjectFilesPage.qml +++ b/plugins/DigitalLibrary/resources/qml/SaveProjectFilesPage.qml @@ -63,7 +63,7 @@ Item anchors.topMargin: UM.Theme.getSize("thin_margin").height validator: RegExpValidator { - regExp: /^[^\\\/\*\?\|\[\]]{0,96}$/ + regExp: /^[\w\-\. ()]{0,255}$/ } text: PrintInformation.jobName @@ -200,7 +200,7 @@ Item anchors.bottom: parent.bottom anchors.right: parent.right text: "Save" - enabled: (asProjectCheckbox.checked || asSlicedCheckbox.checked) && dfFilenameTextfield.text != "" + enabled: (asProjectCheckbox.checked || asSlicedCheckbox.checked) && dfFilenameTextfield.text.length >= 3 onClicked: { diff --git a/plugins/DigitalLibrary/src/DigitalFactoryApiClient.py b/plugins/DigitalLibrary/src/DigitalFactoryApiClient.py index a9a1ab360b..ad87ea9b8a 100644 --- a/plugins/DigitalLibrary/src/DigitalFactoryApiClient.py +++ b/plugins/DigitalLibrary/src/DigitalFactoryApiClient.py @@ -365,12 +365,10 @@ class DigitalFactoryApiClient: :param on_finished: The function to be called after the result is parsed. :param on_error: The function to be called if anything goes wrong. """ - - display_name = re.sub(r"^[\\w\\-\\. ()]+\\.[a-zA-Z0-9]+$", " ", project_name) - Logger.log("i", "Attempt to create new DF project '{}'.".format(display_name)) + Logger.log("i", "Attempt to create new DF project '{}'.".format(project_name)) url = "{}/projects".format(self.CURA_API_ROOT) - data = json.dumps({"data": {"display_name": display_name}}).encode() + data = json.dumps({"data": {"display_name": project_name}}).encode() self._http.put(url, scope = self._scope, data = data, From 86d104afe7f6199103a8f20f25a16a2caf70034d Mon Sep 17 00:00:00 2001 From: Remco Burema Date: Tue, 20 Jul 2021 18:01:44 +0200 Subject: [PATCH 89/96] DL: Allow 1 char filenames (not counting extension). CURA-8395 --- plugins/DigitalLibrary/resources/qml/SaveProjectFilesPage.qml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/DigitalLibrary/resources/qml/SaveProjectFilesPage.qml b/plugins/DigitalLibrary/resources/qml/SaveProjectFilesPage.qml index 6b9361a900..30e3513019 100644 --- a/plugins/DigitalLibrary/resources/qml/SaveProjectFilesPage.qml +++ b/plugins/DigitalLibrary/resources/qml/SaveProjectFilesPage.qml @@ -200,7 +200,7 @@ Item anchors.bottom: parent.bottom anchors.right: parent.right text: "Save" - enabled: (asProjectCheckbox.checked || asSlicedCheckbox.checked) && dfFilenameTextfield.text.length >= 3 + enabled: (asProjectCheckbox.checked || asSlicedCheckbox.checked) && dfFilenameTextfield.text.length >= 1 onClicked: { From 74a611d57706ecd43969443bb7fb730437105cb7 Mon Sep 17 00:00:00 2001 From: Konstantinos Karmas Date: Wed, 21 Jul 2021 11:49:34 +0200 Subject: [PATCH 90/96] Change maximum network printers item count So that it does not make the Local printers button overlap with the add/cancel buttons when the network printers list is full. --- resources/qml/WelcomePages/AddNetworkOrLocalPrinterContent.qml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/resources/qml/WelcomePages/AddNetworkOrLocalPrinterContent.qml b/resources/qml/WelcomePages/AddNetworkOrLocalPrinterContent.qml index 0ea20f052e..edf6fe5974 100644 --- a/resources/qml/WelcomePages/AddNetworkOrLocalPrinterContent.qml +++ b/resources/qml/WelcomePages/AddNetworkOrLocalPrinterContent.qml @@ -54,7 +54,7 @@ Item { id: networkPrinterScrollView - maxItemCountAtOnce: 10 // show at max 10 items at once, otherwise you need to scroll. + maxItemCountAtOnce: 9 // show at max 9 items at once, otherwise you need to scroll. onRefreshButtonClicked: { From 50e0885b5569d974bfd4b03bba920f4669c8b1ee Mon Sep 17 00:00:00 2001 From: Ghostkeeper Date: Wed, 21 Jul 2021 13:10:14 +0200 Subject: [PATCH 91/96] Apply clipping paths in this image QtSVG doesn't support clipping paths. QtSVG only supports the SVG 1.2 Tiny specification. See https://doc.qt.io/qt-5/svgrendering.html for more information on exact support. --- .../resources/images/projects_not_found.svg | 108 ++++++++---------- 1 file changed, 49 insertions(+), 59 deletions(-) diff --git a/plugins/DigitalLibrary/resources/images/projects_not_found.svg b/plugins/DigitalLibrary/resources/images/projects_not_found.svg index 8aee7b797c..ba118ebc0a 100644 --- a/plugins/DigitalLibrary/resources/images/projects_not_found.svg +++ b/plugins/DigitalLibrary/resources/images/projects_not_found.svg @@ -1,62 +1,52 @@ - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + From e04a2b5e92954a4132266e6321185d07927d7779 Mon Sep 17 00:00:00 2001 From: Ghostkeeper Date: Wed, 21 Jul 2021 13:30:19 +0200 Subject: [PATCH 92/96] Also don't translate 'configure' keyword on MacOS Another attempt at finalising CURA-8245. --- resources/qml/Actions.qml | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/resources/qml/Actions.qml b/resources/qml/Actions.qml index bb9adc5b9f..95c6778b87 100644 --- a/resources/qml/Actions.qml +++ b/resources/qml/Actions.qml @@ -180,7 +180,14 @@ Item Action { id: preferencesAction - text: catalog.i18nc("@action:inmenu", "Configure Cura...") + //On MacOS, don't translate the "Configure" word. + //Qt moves the "configure" entry to a different place, and if it got renamed can't find it again when it + //attempts to delete the item upon closing the application, causing a crash. + //In the new location, these items are translated automatically according to the system's language. + //For more information, see: + //- https://doc.qt.io/qt-5/macos-issues.html#menu-bar + //- https://doc.qt.io/qt-5/qmenubar.html#qmenubar-as-a-global-menu-bar + text: (Qt.platform.os == "osx") ? "Configure Cura..." : catalog.i18nc("@action:inmenu", "Configure Cura...") iconName: "configure" } From f611dd603d2ebbd215a19b00cfdf4fb8cc06fc24 Mon Sep 17 00:00:00 2001 From: Konstantinos Karmas Date: Wed, 21 Jul 2021 14:13:50 +0200 Subject: [PATCH 93/96] Remove the "Open file" label from the open file dropdown menu This will make the translations more reasonable (instead of translating "open file" and "from Disk" separately, which could make the some translation results making less sense. CURA-8411 --- plugins/PrepareStage/PrepareMenu.qml | 13 ------------- 1 file changed, 13 deletions(-) diff --git a/plugins/PrepareStage/PrepareMenu.qml b/plugins/PrepareStage/PrepareMenu.qml index 061db0b8f6..cf7665bda6 100644 --- a/plugins/PrepareStage/PrepareMenu.qml +++ b/plugins/PrepareStage/PrepareMenu.qml @@ -120,19 +120,6 @@ Item popup.width = childrenRect.width } - Label - { - text: catalog.i18nc("@menu:header", "Open file") - color: UM.Theme.getColor("text_medium") - font: UM.Theme.getFont("medium") - renderType: Text.NativeRendering - verticalAlignment: Text.AlignVCenter - - width: contentWidth - height: UM.Theme.getSize("action_button").height - leftPadding: UM.Theme.getSize("default_margin").width - } - Repeater { model: prepareMenu.fileProviderModel From 14f0c30795a161f94002f010c9883431d0eb76ec Mon Sep 17 00:00:00 2001 From: Ghostkeeper Date: Wed, 21 Jul 2021 14:18:45 +0200 Subject: [PATCH 94/96] Give secondary buttons a background colour again This background colour is the same as the main background, on which these buttons almost always are situated. However in the cases where they are not, such as the post-processing scripts button, this makes the text easier to read than a completely transparent background colour. Done as a 5 minute fix. --- resources/themes/cura-dark/theme.json | 2 +- resources/themes/cura-light/theme.json | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/resources/themes/cura-dark/theme.json b/resources/themes/cura-dark/theme.json index 0d6fa2f260..457d2092c1 100644 --- a/resources/themes/cura-dark/theme.json +++ b/resources/themes/cura-dark/theme.json @@ -16,7 +16,7 @@ "primary_text": [255, 255, 255, 204], "secondary": [95, 95, 95, 255], - "secondary_button": [0, 0, 0, 0], + "secondary_button": [39, 44, 48, 255], "secondary_button_hover": [85, 85, 87, 255], "secondary_button_text": [255, 255, 255, 255], diff --git a/resources/themes/cura-light/theme.json b/resources/themes/cura-light/theme.json index 93a40d645d..a2727ec12b 100644 --- a/resources/themes/cura-light/theme.json +++ b/resources/themes/cura-light/theme.json @@ -193,7 +193,7 @@ "primary_button_hover": [16, 70, 156, 255], "primary_button_text": [255, 255, 255, 255], - "secondary_button": [255, 255, 255, 0], + "secondary_button": [255, 255, 255, 255], "secondary_button_shadow": [216, 216, 216, 255], "secondary_button_hover": [232, 240, 253, 255], "secondary_button_text": [25, 110, 240, 255], From b7ee3298c2cb281dc4ca9d4880f220d764638f15 Mon Sep 17 00:00:00 2001 From: Jaime van Kessel Date: Fri, 23 Jul 2021 10:40:30 +0200 Subject: [PATCH 95/96] Add extra logging to auth server --- cura/API/Account.py | 2 +- cura/OAuth2/LocalAuthorizationServer.py | 7 +++++-- 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/cura/API/Account.py b/cura/API/Account.py index 728d0690a3..2e48a040ad 100644 --- a/cura/API/Account.py +++ b/cura/API/Account.py @@ -109,7 +109,6 @@ class Account(QObject): self._authorization_service.accessTokenChanged.connect(self._onAccessTokenChanged) self._authorization_service.loadAuthDataFromPreferences() - @pyqtProperty(int, notify=syncStateChanged) def syncState(self): return self._sync_state @@ -178,6 +177,7 @@ class Account(QObject): if error_message: if self._error_message: self._error_message.hide() + Logger.log("w", "Failed to login: %s", error_message) self._error_message = Message(error_message, title = i18n_catalog.i18nc("@info:title", "Login failed")) self._error_message.show() self._logged_in = False diff --git a/cura/OAuth2/LocalAuthorizationServer.py b/cura/OAuth2/LocalAuthorizationServer.py index ac14b00985..219191c295 100644 --- a/cura/OAuth2/LocalAuthorizationServer.py +++ b/cura/OAuth2/LocalAuthorizationServer.py @@ -54,6 +54,7 @@ class LocalAuthorizationServer: if self._web_server: # If the server is already running (because of a previously aborted auth flow), we don't have to start it. # We still inject the new verification code though. + Logger.log("d", "Auth web server was already running. Updating the verification code") self._web_server.setVerificationCode(verification_code) return @@ -85,6 +86,7 @@ class LocalAuthorizationServer: except OSError: # OS error can happen if the socket was already closed. We really don't care about that case. pass + Logger.log("d", "Local oauth2 web server was shut down") self._web_server = None self._web_server_thread = None @@ -96,12 +98,13 @@ class LocalAuthorizationServer: :return: None """ + Logger.log("d", "Local web server for authorization has started") if self._web_server: if sys.platform == "win32": try: self._web_server.serve_forever() - except OSError as e: - Logger.warning(str(e)) + except OSError: + Logger.logException("w", "An exception happened while serving the auth server") else: # Leave the default behavior in non-windows platforms self._web_server.serve_forever() From a4f6e94ae0a038119701f45380cc232b71b2abe7 Mon Sep 17 00:00:00 2001 From: Ghostkeeper Date: Fri, 23 Jul 2021 15:16:38 +0200 Subject: [PATCH 96/96] Update the sync-storage path every time you sync Instead of updating the storage path every time you add or remove a removable drive, we now update the storage path every time you press the button to sync. That way this detail has no impact on performance of other parts of Cura if they don't use this button. It also makes the code a bit simpler. The only downside is that this FileDialog then contains state, instead of automatically syncing with the MaterialManagement property for its folder property. I see that as a lesser of two evils. Contributes to issue CURA-8055. --- .../Models/MaterialManagementModel.py | 42 +++++-------------- .../Preferences/Materials/MaterialsPage.qml | 2 +- 2 files changed, 11 insertions(+), 33 deletions(-) diff --git a/cura/Machines/Models/MaterialManagementModel.py b/cura/Machines/Models/MaterialManagementModel.py index 85f208d8b0..6663dbdae1 100644 --- a/cura/Machines/Models/MaterialManagementModel.py +++ b/cura/Machines/Models/MaterialManagementModel.py @@ -21,16 +21,6 @@ if TYPE_CHECKING: catalog = i18nCatalog("cura") class MaterialManagementModel(QObject): - """Proxy class to the materials page in the preferences. - - This class handles the actions in that page, such as creating new materials, renaming them, etc. - """ - def __init__(self, parent: QObject) -> None: - super().__init__(parent) - cura_application = cura.CuraApplication.CuraApplication.getInstance() - self._preferred_export_all_path = None # type: Optional[QUrl] # Path to export all materials to. None if not yet initialised. - cura_application.getOutputDeviceManager().outputDevicesChanged.connect(self._onOutputDevicesChanged) - favoritesChanged = pyqtSignal(str) """Triggered when a favorite is added or removed. @@ -271,25 +261,8 @@ class MaterialManagementModel(QObject): except ValueError: # Material was not in the favorites list. Logger.log("w", "Material {material_base_file} was already not a favorite material.".format(material_base_file = material_base_file)) - def _onOutputDevicesChanged(self) -> None: - """ - When the list of output devices changes, we may want to update the - preferred export path. - """ - cura_application = cura.CuraApplication.CuraApplication.getInstance() - device_manager = cura_application.getOutputDeviceManager() - devices = device_manager.getOutputDevices() - for device in devices: - if device.__class__.__name__ == "RemovableDriveOutputDevice": - self._preferred_export_all_path = QUrl.fromLocalFile(device.getId()) - break - else: # No removable drives? Use local path. - self._preferred_export_all_path = cura_application.getDefaultPath("dialog_material_path") - self.outputDevicesChanged.emit() - - outputDevicesChanged = pyqtSignal() # Triggered when adding or removing removable drives. - @pyqtProperty(QUrl, notify = outputDevicesChanged) - def preferredExportAllPath(self) -> QUrl: + @pyqtSlot(result = QUrl) + def getPreferredExportAllPath(self) -> QUrl: """ Get the preferred path to export materials to. @@ -297,9 +270,14 @@ class MaterialManagementModel(QObject): file path. :return: The preferred path to export all materials to. """ - if self._preferred_export_all_path is None: # Not initialised yet. Can happen when output devices changed before class got created. - self._onOutputDevicesChanged() - return self._preferred_export_all_path + cura_application = cura.CuraApplication.CuraApplication.getInstance() + device_manager = cura_application.getOutputDeviceManager() + devices = device_manager.getOutputDevices() + for device in devices: + if device.__class__.__name__ == "RemovableDriveOutputDevice": + return QUrl.fromLocalFile(device.getId()) + else: # No removable drives? Use local path. + return cura_application.getDefaultPath("dialog_material_path") @pyqtSlot(QUrl) def exportAll(self, file_path: QUrl) -> None: diff --git a/resources/qml/Preferences/Materials/MaterialsPage.qml b/resources/qml/Preferences/Materials/MaterialsPage.qml index 8d6dfdfb3a..4de3ad918b 100644 --- a/resources/qml/Preferences/Materials/MaterialsPage.qml +++ b/resources/qml/Preferences/Materials/MaterialsPage.qml @@ -201,6 +201,7 @@ Item onClicked: { forceActiveFocus(); + exportAllMaterialsDialog.folder = base.materialManagementModel.getPreferredExportAllPath(); exportAllMaterialsDialog.open(); } visible: Cura.MachineManager.activeMachine.supportsMaterialExport @@ -388,7 +389,6 @@ Item title: catalog.i18nc("@title:window", "Export All Materials") selectExisting: false nameFilters: ["Material archives (*.umm)", "All files (*)"] - folder: base.materialManagementModel.preferredExportAllPath onAccepted: { base.materialManagementModel.exportAll(fileUrl);