Merge branch '4.10'

This commit is contained in:
Ghostkeeper 2021-06-24 14:19:40 +02:00
commit 84b5b19584
No known key found for this signature in database
GPG Key ID: D2A8871EE34EC59A
7 changed files with 8 additions and 113 deletions

View File

@ -2,10 +2,9 @@
# Cura is released under the terms of the LGPLv3 or higher. # Cura is released under the terms of the LGPLv3 or higher.
import copy # To duplicate materials. 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 from typing import Any, Dict, Optional, TYPE_CHECKING
import uuid # To generate new GUIDs for new materials. 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.i18n import i18nCatalog
from UM.Logger import Logger 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. 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) favoritesChanged = pyqtSignal(str)
"""Triggered when a favorite is added or removed. """Triggered when a favorite is added or removed.
@ -270,52 +264,3 @@ class MaterialManagementModel(QObject):
self.favoritesChanged.emit(material_base_file) self.favoritesChanged.emit(material_base_file)
except ValueError: # Material was not in the favorites list. 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)) 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())

View File

@ -1,10 +1,10 @@
# Copyright (c) 2021 Ultimaker B.V. # Copyright (c) 2021 Ultimaker B.V.
# Cura is released under the terms of the LGPLv3 or higher. # 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 import keyring
from keyring.backend import KeyringBackend from keyring.backend import KeyringBackend
from keyring.errors import NoKeyringError, PasswordSetError, KeyringError from keyring.errors import NoKeyringError, PasswordSetError, KeyringLocked
from UM.Logger import Logger from UM.Logger import Logger
@ -14,24 +14,13 @@ if TYPE_CHECKING:
# Need to do some extra workarounds on windows: # Need to do some extra workarounds on windows:
import sys import sys
from UM.Platform import Platform from UM.Platform import Platform
class _KeychainDenied(Exception):
pass
if Platform.isWindows() and hasattr(sys, "frozen"): if Platform.isWindows() and hasattr(sys, "frozen"):
import win32timezone import win32timezone
from keyring.backends.Windows import WinVaultKeyring from keyring.backends.Windows import WinVaultKeyring
keyring.set_keyring(WinVaultKeyring()) keyring.set_keyring(WinVaultKeyring())
if Platform.isOSX() and hasattr(sys, "frozen"): if Platform.isOSX() and hasattr(sys, "frozen"):
from keyring.backends.macOS import Keyring 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()) keyring.set_keyring(Keyring())
else:
KeychainDenied = _KeychainDenied
# Even if errors happen, we don't want this stored locally: # Even if errors happen, we don't want this stored locally:
DONT_EVER_STORE_LOCALLY: List[str] = ["refresh_token"] DONT_EVER_STORE_LOCALLY: List[str] = ["refresh_token"]
@ -50,7 +39,7 @@ class KeyringAttribute:
self._store_secure = False self._store_secure = False
Logger.logException("w", "No keyring backend present") Logger.logException("w", "No keyring backend present")
return getattr(instance, self._name) return getattr(instance, self._name)
except KeychainDenied: except KeyringLocked:
self._store_secure = False self._store_secure = False
Logger.log("i", "Access to the keyring was denied.") Logger.log("i", "Access to the keyring was denied.")
return getattr(instance, self._name) return getattr(instance, self._name)
@ -63,7 +52,7 @@ class KeyringAttribute:
if value is not None: if value is not None:
try: try:
keyring.set_password("cura", self._keyring_name, value) keyring.set_password("cura", self._keyring_name, value)
except PasswordSetError: except (PasswordSetError, KeyringLocked):
self._store_secure = False self._store_secure = False
if self._name not in DONT_EVER_STORE_LOCALLY: if self._name not in DONT_EVER_STORE_LOCALLY:
setattr(instance, self._name, value) setattr(instance, self._name, value)

View File

@ -86,14 +86,6 @@ class GlobalStack(CuraContainerStack):
def supportsNetworkConnection(self): def supportsNetworkConnection(self):
return self.getMetaDataEntry("supports_network_connection", False) 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 @classmethod
def getLoadingPriority(cls) -> int: def getLoadingPriority(cls) -> int:
return 2 return 2

View File

@ -22,8 +22,7 @@
"0": "ultimaker2_plus_connect_extruder_0" "0": "ultimaker2_plus_connect_extruder_0"
}, },
"supports_usb_connection": false, "supports_usb_connection": false,
"supports_network_connection": true, "supports_network_connection": true
"supports_material_export": true
}, },
"overrides": { "overrides": {

View File

@ -27,7 +27,6 @@
"first_start_actions": [ "DiscoverUM3Action" ], "first_start_actions": [ "DiscoverUM3Action" ],
"supported_actions": [ "DiscoverUM3Action" ], "supported_actions": [ "DiscoverUM3Action" ],
"supports_usb_connection": false, "supports_usb_connection": false,
"supports_material_export": true,
"weight": -1, "weight": -1,
"firmware_update_info": { "firmware_update_info": {
"id": 213482, "id": 213482,

View File

@ -28,7 +28,6 @@
"supported_actions": [ "DiscoverUM3Action" ], "supported_actions": [ "DiscoverUM3Action" ],
"supports_usb_connection": false, "supports_usb_connection": false,
"supports_network_connection": true, "supports_network_connection": true,
"supports_material_export": true,
"weight": -2, "weight": -2,
"firmware_update_info": { "firmware_update_info": {
"id": 9051, "id": 9051,

View File

@ -1,5 +1,5 @@
// Copyright (c) 2021 Ultimaker B.V. // Copyright (c) 2018 Ultimaker B.V.
// Cura is released under the terms of the LGPLv3 or higher. // Uranium is released under the terms of the LGPLv3 or higher.
import QtQuick 2.7 import QtQuick 2.7
import QtQuick.Controls 1.4 import QtQuick.Controls 1.4
@ -191,20 +191,6 @@ Item
} }
enabled: base.hasCurrentItem 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 { 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 MessageDialog
{ {
id: messageDialog id: messageDialog