mirror of
https://git.mirrors.martin98.com/https://github.com/Ultimaker/Cura
synced 2025-08-13 04:29:01 +08:00
Merge branch '4.10' of github.com:Ultimaker/Cura
This commit is contained in:
commit
7e7a09ffa7
@ -166,6 +166,9 @@ class Backup:
|
||||
Logger.log("d", "Moving preferences file from %s to %s", backup_preferences_file, preferences_file)
|
||||
shutil.move(backup_preferences_file, preferences_file)
|
||||
|
||||
# Read the preferences from the newly restored configuration (or else the cached Preferences will override the restored ones)
|
||||
self._application.readPreferencesFromConfiguration()
|
||||
|
||||
# Restore the obfuscated settings
|
||||
self._illuminate(**secrets)
|
||||
|
||||
@ -191,7 +194,10 @@ class Backup:
|
||||
Resources.factoryReset()
|
||||
Logger.log("d", "Extracting backup to location: %s", target_path)
|
||||
try:
|
||||
archive.extractall(target_path)
|
||||
name_list = archive.namelist()
|
||||
for archive_filename in name_list:
|
||||
archive.extract(archive_filename, target_path)
|
||||
CuraApplication.getInstance().processEvents()
|
||||
except (PermissionError, EnvironmentError):
|
||||
Logger.logException("e", "Unable to extract the backup due to permission or file system errors.")
|
||||
return False
|
||||
|
@ -114,6 +114,7 @@ class QualitySettingsModel(ListModel):
|
||||
global_container = None if len(global_containers) == 0 else global_containers[0]
|
||||
extruders_containers = {pos: container_registry.findContainers(id = quality_changes_group.metadata_per_extruder[pos]["id"]) for pos in quality_changes_group.metadata_per_extruder}
|
||||
extruders_container = {pos: None if not containers else containers[0] for pos, containers in extruders_containers.items()}
|
||||
quality_changes_metadata = None
|
||||
if self._selected_position == self.GLOBAL_STACK_POSITION and global_container:
|
||||
quality_changes_metadata = global_container.getMetaData()
|
||||
else:
|
||||
|
@ -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
|
||||
from typing import Type, TYPE_CHECKING, Optional, List, Union
|
||||
|
||||
import keyring
|
||||
from keyring.backend import KeyringBackend
|
||||
from keyring.errors import NoKeyringError, PasswordSetError
|
||||
from keyring.errors import NoKeyringError, PasswordSetError, KeyringError
|
||||
|
||||
from UM.Logger import Logger
|
||||
|
||||
@ -14,13 +14,24 @@ 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"]
|
||||
@ -39,6 +50,10 @@ class KeyringAttribute:
|
||||
self._store_secure = False
|
||||
Logger.logException("w", "No keyring backend present")
|
||||
return getattr(instance, self._name)
|
||||
except KeychainDenied:
|
||||
self._store_secure = False
|
||||
Logger.log("i", "Access to the keyring was denied.")
|
||||
return getattr(instance, self._name)
|
||||
else:
|
||||
return getattr(instance, self._name)
|
||||
|
||||
|
@ -5,7 +5,6 @@ import threading
|
||||
from datetime import datetime
|
||||
from typing import Any, Dict, Optional
|
||||
|
||||
import sentry_sdk
|
||||
from PyQt5.QtNetwork import QNetworkReply
|
||||
|
||||
from UM.Job import Job
|
||||
@ -99,13 +98,7 @@ class CreateBackupJob(Job):
|
||||
if HttpRequestManager.safeHttpStatus(reply) == 400:
|
||||
errors = json.loads(replyText)["errors"]
|
||||
if "moreThanMaximum" in [error["code"] for error in errors if error["meta"] and error["meta"]["field_name"] == "backup_size"]:
|
||||
if self._backup_zip is None: # will never happen; keep mypy happy
|
||||
zip_error = "backup is None."
|
||||
else:
|
||||
zip_error = "{} exceeds max size.".format(str(len(self._backup_zip)))
|
||||
sentry_sdk.capture_message("backup failed: {}".format(zip_error), level ="warning")
|
||||
self.backup_upload_error_message = catalog.i18nc("@error:file_size", "The backup exceeds the maximum file size.")
|
||||
from sentry_sdk import capture_message
|
||||
|
||||
self._job_done.set()
|
||||
return
|
||||
|
@ -34,6 +34,9 @@ class DrivePluginExtension(QObject, Extension):
|
||||
# Signal emitted when preferences changed (like auto-backup).
|
||||
preferencesChanged = pyqtSignal()
|
||||
|
||||
# Signal emitted when the id of the backup-to-be-restored is changed
|
||||
backupIdBeingRestoredChanged = pyqtSignal(arguments = ["backup_id_being_restored"])
|
||||
|
||||
DATE_FORMAT = "%d/%m/%Y %H:%M:%S"
|
||||
|
||||
def __init__(self) -> None:
|
||||
@ -45,6 +48,7 @@ class DrivePluginExtension(QObject, Extension):
|
||||
self._backups = [] # type: List[Dict[str, Any]]
|
||||
self._is_restoring_backup = False
|
||||
self._is_creating_backup = False
|
||||
self._backup_id_being_restored = ""
|
||||
|
||||
# Initialize services.
|
||||
preferences = CuraApplication.getInstance().getPreferences()
|
||||
@ -52,6 +56,7 @@ class DrivePluginExtension(QObject, Extension):
|
||||
|
||||
# Attach signals.
|
||||
CuraApplication.getInstance().getCuraAPI().account.loginStateChanged.connect(self._onLoginStateChanged)
|
||||
CuraApplication.getInstance().applicationShuttingDown.connect(self._onApplicationShuttingDown)
|
||||
self._drive_api_service.restoringStateChanged.connect(self._onRestoringStateChanged)
|
||||
self._drive_api_service.creatingStateChanged.connect(self._onCreatingStateChanged)
|
||||
|
||||
@ -75,6 +80,9 @@ class DrivePluginExtension(QObject, Extension):
|
||||
if self._drive_window:
|
||||
self._drive_window.show()
|
||||
|
||||
def _onApplicationShuttingDown(self):
|
||||
self._drive_window.hide()
|
||||
|
||||
def _autoBackup(self) -> None:
|
||||
preferences = CuraApplication.getInstance().getPreferences()
|
||||
if preferences.getValue(Settings.AUTO_BACKUP_ENABLED_PREFERENCE_KEY) and self._isLastBackupTooLongAgo():
|
||||
@ -100,10 +108,11 @@ class DrivePluginExtension(QObject, Extension):
|
||||
if logged_in:
|
||||
self.refreshBackups()
|
||||
|
||||
def _onRestoringStateChanged(self, is_restoring: bool = False, error_message: str = None) -> None:
|
||||
def _onRestoringStateChanged(self, is_restoring: bool = False, error_message: Optional[str] = None) -> None:
|
||||
self._is_restoring_backup = is_restoring
|
||||
self.restoringStateChanged.emit()
|
||||
if error_message:
|
||||
self.backupIdBeingRestored = ""
|
||||
Message(error_message, title = catalog.i18nc("@info:title", "Backup")).show()
|
||||
|
||||
def _onCreatingStateChanged(self, is_creating: bool = False, error_message: str = None) -> None:
|
||||
@ -152,6 +161,7 @@ class DrivePluginExtension(QObject, Extension):
|
||||
for backup in self._backups:
|
||||
if backup.get("backup_id") == backup_id:
|
||||
self._drive_api_service.restoreBackup(backup)
|
||||
self.setBackupIdBeingRestored(backup_id)
|
||||
return
|
||||
Logger.log("w", "Unable to find backup with the ID %s", backup_id)
|
||||
|
||||
@ -166,3 +176,12 @@ class DrivePluginExtension(QObject, Extension):
|
||||
def _backupDeletedCallback(self, success: bool):
|
||||
if success:
|
||||
self.refreshBackups()
|
||||
|
||||
def setBackupIdBeingRestored(self, backup_id_being_restored: str) -> None:
|
||||
if backup_id_being_restored != self._backup_id_being_restored:
|
||||
self._backup_id_being_restored = backup_id_being_restored
|
||||
self.backupIdBeingRestoredChanged.emit()
|
||||
|
||||
@pyqtProperty(str, fset = setBackupIdBeingRestored, notify = backupIdBeingRestoredChanged)
|
||||
def backupIdBeingRestored(self) -> str:
|
||||
return self._backup_id_being_restored
|
||||
|
@ -71,6 +71,7 @@ Item
|
||||
text: catalog.i18nc("@button", "Restore")
|
||||
enabled: !CuraDrive.isCreatingBackup && !CuraDrive.isRestoringBackup
|
||||
onClicked: confirmRestoreDialog.visible = true
|
||||
busy: CuraDrive.backupIdBeingRestored == modelData.backup_id && CuraDrive.isRestoringBackup
|
||||
}
|
||||
|
||||
UM.SimpleButton
|
||||
|
@ -174,7 +174,7 @@ msgstr "Pokusil se obnovit zálohu Cura, která je vyšší než aktuální verz
|
||||
#: /home/trin/Gedeeld/Projects/Cura/cura/Backups/Backup.py:157
|
||||
msgctxt "@info:backup_failed"
|
||||
msgid "The following error occurred while trying to restore a Cura backup:"
|
||||
msgstr ""
|
||||
msgstr "Během obnovení zálohy Cura se vyskytly následující chyby:"
|
||||
|
||||
#: /home/trin/Gedeeld/Projects/Cura/cura/BuildVolume.py:98
|
||||
msgctxt "@info:status"
|
||||
@ -2268,7 +2268,7 @@ msgstr "Zobrazit online manuály"
|
||||
#: /home/trin/Gedeeld/Projects/Cura/plugins/MonitorStage/MonitorMain.qml:172
|
||||
msgctxt "@info"
|
||||
msgid "In order to monitor your print from Cura, please connect the printer."
|
||||
msgstr ""
|
||||
msgstr "Abyste mohli monitorovat tisk z Cury, připojte prosím tiskárnu."
|
||||
|
||||
#: /home/trin/Gedeeld/Projects/Cura/plugins/PerObjectSettingsTool/PerObjectSettingsPanel.qml:42
|
||||
msgctxt "@label"
|
||||
@ -2393,7 +2393,7 @@ msgstr "Šířka čáry"
|
||||
#: /home/trin/Gedeeld/Projects/Cura/plugins/SimulationView/SimulationViewMenuComponent.qml:130
|
||||
msgctxt "@label:listbox"
|
||||
msgid "Flow"
|
||||
msgstr ""
|
||||
msgstr "Průtok"
|
||||
|
||||
#: /home/trin/Gedeeld/Projects/Cura/plugins/SimulationView/SimulationViewMenuComponent.qml:171
|
||||
msgctxt "@label"
|
||||
@ -3385,12 +3385,12 @@ msgstr "Přední pohled"
|
||||
#: /home/trin/Gedeeld/Projects/Cura/resources/qml/Actions.qml:147
|
||||
msgctxt "@action:inmenu menubar:view"
|
||||
msgid "Top View"
|
||||
msgstr "Pohled ze shora"
|
||||
msgstr "Pohled seshora"
|
||||
|
||||
#: /home/trin/Gedeeld/Projects/Cura/resources/qml/Actions.qml:154
|
||||
msgctxt "@action:inmenu menubar:view"
|
||||
msgid "Bottom View"
|
||||
msgstr ""
|
||||
msgstr "Pohled zezdola"
|
||||
|
||||
#: /home/trin/Gedeeld/Projects/Cura/resources/qml/Actions.qml:161
|
||||
msgctxt "@action:inmenu menubar:view"
|
||||
@ -4627,7 +4627,7 @@ msgstr "Export"
|
||||
#: /home/trin/Gedeeld/Projects/Cura/resources/qml/Preferences/Materials/MaterialsPage.qml:199
|
||||
msgctxt "@action:button Sending materials to printers"
|
||||
msgid "Sync with Printers"
|
||||
msgstr ""
|
||||
msgstr "Synchronizovat s tiskárnami"
|
||||
|
||||
#: /home/trin/Gedeeld/Projects/Cura/resources/qml/Preferences/Materials/MaterialsPage.qml:248
|
||||
msgctxt "@action:label"
|
||||
@ -4681,7 +4681,7 @@ msgstr "Úspěšné exportování materiálu do <filename>%1</filename>"
|
||||
#: /home/trin/Gedeeld/Projects/Cura/resources/qml/Preferences/Materials/MaterialsPage.qml:388
|
||||
msgctxt "@title:window"
|
||||
msgid "Export All Materials"
|
||||
msgstr ""
|
||||
msgstr "Exportovat všechny materiály"
|
||||
|
||||
#: /home/trin/Gedeeld/Projects/Cura/resources/qml/Preferences/Materials/MaterialsView.qml:72
|
||||
msgctxt "@title"
|
||||
@ -5252,7 +5252,7 @@ msgstr "Přední pohled"
|
||||
#: /home/trin/Gedeeld/Projects/Cura/resources/qml/ViewOrientationControls.qml:53
|
||||
msgctxt "@info:tooltip"
|
||||
msgid "Top View"
|
||||
msgstr "Pohled ze shora"
|
||||
msgstr "Pohled seshora"
|
||||
|
||||
#: /home/trin/Gedeeld/Projects/Cura/resources/qml/ViewOrientationControls.qml:66
|
||||
msgctxt "@info:tooltip"
|
||||
@ -5593,12 +5593,12 @@ msgstr "Zapisovač Cura profilu"
|
||||
#: DigitalLibrary/plugin.json
|
||||
msgctxt "description"
|
||||
msgid "Connects to the Digital Library, allowing Cura to open files from and save files to the Digital Library."
|
||||
msgstr ""
|
||||
msgstr "Připojuje k Digitální knihovně. Umožňuje Cuře otevírat a ukládat soubory z a do Digitální knihovny."
|
||||
|
||||
#: DigitalLibrary/plugin.json
|
||||
msgctxt "name"
|
||||
msgid "Ultimaker Digital Library"
|
||||
msgstr ""
|
||||
msgstr "Digitální knihovna Ultimaker"
|
||||
|
||||
#: FirmwareUpdateChecker/plugin.json
|
||||
msgctxt "description"
|
||||
@ -6073,22 +6073,22 @@ msgstr "Aktualizace verze 4.7 na 4.8"
|
||||
#: VersionUpgrade/VersionUpgrade48to49/plugin.json
|
||||
msgctxt "description"
|
||||
msgid "Upgrades configurations from Cura 4.8 to Cura 4.9."
|
||||
msgstr ""
|
||||
msgstr "Aktualizuje konfigurace z Cura 4.8 na Cura 4.9."
|
||||
|
||||
#: VersionUpgrade/VersionUpgrade48to49/plugin.json
|
||||
msgctxt "name"
|
||||
msgid "Version Upgrade 4.8 to 4.9"
|
||||
msgstr ""
|
||||
msgstr "Aktualizace verze 4.8 na 4.9"
|
||||
|
||||
#: VersionUpgrade/VersionUpgrade49to410/plugin.json
|
||||
msgctxt "description"
|
||||
msgid "Upgrades configurations from Cura 4.9 to Cura 4.10."
|
||||
msgstr ""
|
||||
msgstr "Aktualizuje konfigurace z Cura 4.9 na Cura 4.10."
|
||||
|
||||
#: VersionUpgrade/VersionUpgrade49to410/plugin.json
|
||||
msgctxt "name"
|
||||
msgid "Version Upgrade 4.9 to 4.10"
|
||||
msgstr ""
|
||||
msgstr "Aktualizace verze 4.9 na 4.10"
|
||||
|
||||
#: X3DReader/plugin.json
|
||||
msgctxt "description"
|
||||
|
@ -3200,7 +3200,7 @@ msgstr "Maximální vzdálenost Combing-u bez retrakce"
|
||||
#: fdmprinter.def.json
|
||||
msgctxt "retraction_combing_max_distance description"
|
||||
msgid "When greater than zero, combing travel moves that are longer than this distance will use retraction. If set to zero, there is no maximum and combing moves will not use retraction."
|
||||
msgstr ""
|
||||
msgstr "Pokud je větší než nula, combingové pohyby delší než tato vzdálenost budou používat retrakci. Nula znamená, že se při combingových pohybech retrakce provádět nebudou."
|
||||
|
||||
#: fdmprinter.def.json
|
||||
msgctxt "travel_retract_before_outer_wall label"
|
||||
|
Binary file not shown.
Before Width: | Height: | Size: 248 KiB After Width: | Height: | Size: 339 KiB |
@ -59,6 +59,7 @@ ToolTip
|
||||
color: UM.Theme.getColor("tooltip")
|
||||
target: Qt.point(targetPoint.x - tooltip.x, targetPoint.y - tooltip.y)
|
||||
arrowSize: UM.Theme.getSize("default_arrow").width
|
||||
visible: tooltip.height != 0
|
||||
}
|
||||
|
||||
contentItem: Label
|
||||
|
Loading…
x
Reference in New Issue
Block a user