From 8ade68dbef50f90ffabbc3d6014a164ffa3c3cf6 Mon Sep 17 00:00:00 2001 From: Konstantinos Karmas Date: Wed, 23 Jun 2021 11:20:35 +0200 Subject: [PATCH 1/3] Catch the KeyringLocked error instead of the MacOS specific Turns out that when the KeychainDenied error is raised, it is being caught by the macOS keyring api and the non-macOS-specific KeyringLocked error is raised instead, so we need to catch this one. CURA-8332 --- cura/OAuth2/KeyringAttribute.py | 17 +++-------------- 1 file changed, 3 insertions(+), 14 deletions(-) diff --git a/cura/OAuth2/KeyringAttribute.py b/cura/OAuth2/KeyringAttribute.py index 1d6f329ea9..1a522b4061 100644 --- a/cura/OAuth2/KeyringAttribute.py +++ b/cura/OAuth2/KeyringAttribute.py @@ -1,10 +1,10 @@ # Copyright (c) 2021 Ultimaker B.V. # Cura is released under the terms of the LGPLv3 or higher. -from typing import Type, TYPE_CHECKING, Optional, List, Union +from typing import Type, TYPE_CHECKING, Optional, List import keyring from keyring.backend import KeyringBackend -from keyring.errors import NoKeyringError, PasswordSetError, KeyringError +from keyring.errors import NoKeyringError, PasswordSetError, KeyringLocked from UM.Logger import Logger @@ -14,24 +14,13 @@ if TYPE_CHECKING: # Need to do some extra workarounds on windows: import sys from UM.Platform import Platform - - -class _KeychainDenied(Exception): - pass - - if Platform.isWindows() and hasattr(sys, "frozen"): import win32timezone from keyring.backends.Windows import WinVaultKeyring keyring.set_keyring(WinVaultKeyring()) if Platform.isOSX() and hasattr(sys, "frozen"): from keyring.backends.macOS import Keyring - from keyring.backends.macOS.api import KeychainDenied as _KeychainDeniedMacOS - KeychainDenied: Union[Type[_KeychainDenied], Type[_KeychainDeniedMacOS]] = _KeychainDeniedMacOS keyring.set_keyring(Keyring()) -else: - KeychainDenied = _KeychainDenied - # Even if errors happen, we don't want this stored locally: DONT_EVER_STORE_LOCALLY: List[str] = ["refresh_token"] @@ -50,7 +39,7 @@ class KeyringAttribute: self._store_secure = False Logger.logException("w", "No keyring backend present") return getattr(instance, self._name) - except KeychainDenied: + except KeyringLocked: self._store_secure = False Logger.log("i", "Access to the keyring was denied.") return getattr(instance, self._name) From ceca0c417a5a98c0cd0d2e2dd72ee25d66c62c06 Mon Sep 17 00:00:00 2001 From: Konstantinos Karmas Date: Wed, 23 Jun 2021 11:22:12 +0200 Subject: [PATCH 2/3] Catch the KeyringLocked also when setting the token in the keyring CURA-8332 --- cura/OAuth2/KeyringAttribute.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cura/OAuth2/KeyringAttribute.py b/cura/OAuth2/KeyringAttribute.py index 1a522b4061..9bb6e3c267 100644 --- a/cura/OAuth2/KeyringAttribute.py +++ b/cura/OAuth2/KeyringAttribute.py @@ -52,7 +52,7 @@ class KeyringAttribute: if value is not None: try: keyring.set_password("cura", self._keyring_name, value) - except PasswordSetError: + except (PasswordSetError, KeyringLocked): self._store_secure = False if self._name not in DONT_EVER_STORE_LOCALLY: setattr(instance, self._name, value) From 4d29de45796dc42f76c774a216a0601bb57cf790 Mon Sep 17 00:00:00 2001 From: Ghostkeeper Date: Thu, 24 Jun 2021 14:11:48 +0200 Subject: [PATCH 3/3] Revert CURA-8055 in the 4.10 branch. This should not have been merged in there. Revert "Change file extension to .umm" This reverts commit 56db7f7144083df4bca77746d7ee30f2a54fda36. Revert "Re-enable compression" This reverts commit 62bc9be22bbc5595dbfce69893163c3a0ebc4415. Revert "Add documentation" This reverts commit e9031f1aff5d40f3c69ac625edf11963a3253eb8. Revert "Fix writing bytes to string-stream" This reverts commit 66b2825a667f9aa9618005d2a5875383a3658f4f. Revert "Hide button entirely if no export is available" This reverts commit ec727e1068c3ac2cab7f95fb88c5d4d101e28e17. Revert "Basic implementation of exporting all materials in a .zip archive" This reverts commit bdcaef134f556f455f352786123476ec40e3ae4c. Revert "Implement default path for exporting all materials" This reverts commit e66783664bf73dd9b1e3c6af6f01321763470d2e. Revert "Implement a sync button and file dialogue to export all materials" This reverts commit abba3bdd10a994a1b38bcb426a27ba379febeac7. Revert "Add notion of whether printers support the material export archive" This reverts commit f436cb8e7b879a8913b25f2a049413ec0721f1c5. --- .../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, 4 insertions(+), 98 deletions(-) diff --git a/cura/Machines/Models/MaterialManagementModel.py b/cura/Machines/Models/MaterialManagementModel.py index 85f208d8b0..cd35a78353 100644 --- a/cura/Machines/Models/MaterialManagementModel.py +++ b/cura/Machines/Models/MaterialManagementModel.py @@ -2,10 +2,9 @@ # Cura is released under the terms of the LGPLv3 or higher. import copy # To duplicate materials. -from PyQt5.QtCore import pyqtProperty, pyqtSignal, pyqtSlot, QObject, QUrl +from PyQt5.QtCore import QObject, pyqtSignal, pyqtSlot # To allow the preference page proxy to be used from the actual preferences page. 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 @@ -25,11 +24,6 @@ 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. @@ -270,52 +264,3 @@ 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 282034c0ee..2c7cbf5e25 100755 --- a/cura/Settings/GlobalStack.py +++ b/cura/Settings/GlobalStack.py @@ -86,14 +86,6 @@ 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 46c615a262..c0ddcf813f 100644 --- a/resources/definitions/ultimaker2_plus_connect.def.json +++ b/resources/definitions/ultimaker2_plus_connect.def.json @@ -22,8 +22,7 @@ "0": "ultimaker2_plus_connect_extruder_0" }, "supports_usb_connection": false, - "supports_network_connection": true, - "supports_material_export": true + "supports_network_connection": true }, "overrides": { diff --git a/resources/definitions/ultimaker_s3.def.json b/resources/definitions/ultimaker_s3.def.json index 43f32a96dc..962bff3fa0 100644 --- a/resources/definitions/ultimaker_s3.def.json +++ b/resources/definitions/ultimaker_s3.def.json @@ -27,7 +27,6 @@ "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 71de826953..8a9880c31a 100644 --- a/resources/definitions/ultimaker_s5.def.json +++ b/resources/definitions/ultimaker_s5.def.json @@ -28,7 +28,6 @@ "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 8d6dfdfb3a..791d6685de 100644 --- a/resources/qml/Preferences/Materials/MaterialsPage.qml +++ b/resources/qml/Preferences/Materials/MaterialsPage.qml @@ -1,5 +1,5 @@ -// Copyright (c) 2021 Ultimaker B.V. -// Cura is released under the terms of the LGPLv3 or higher. +// Copyright (c) 2018 Ultimaker B.V. +// Uranium is released under the terms of the LGPLv3 or higher. import QtQuick 2.7 import QtQuick.Controls 1.4 @@ -191,20 +191,6 @@ 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 { @@ -382,20 +368,6 @@ 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