Merge branch 'feature-backup-manager' of https://github.com/Ultimaker/Cura into feature-backup-manager

* 'feature-backup-manager' of https://github.com/Ultimaker/Cura:
  Do not safe data after restoring backup
  Rudimentary restore functionality
  Fix pre-installed Ultimaker PC material
This commit is contained in:
ChrisTerBeke 2018-05-11 18:08:11 +02:00
commit c678b401e3
No known key found for this signature in database
GPG Key ID: A49F1AB9D7E0C263
4 changed files with 54 additions and 9 deletions

View File

@ -2,6 +2,8 @@
# Cura is released under the terms of the LGPLv3 or higher. # Cura is released under the terms of the LGPLv3 or higher.
import io import io
import os import os
import shutil
from typing import Optional from typing import Optional
from zipfile import ZipFile, ZIP_DEFLATED, BadZipfile from zipfile import ZipFile, ZIP_DEFLATED, BadZipfile
@ -17,8 +19,7 @@ class Backup:
""" """
# These files should be ignored when making a backup. # These files should be ignored when making a backup.
# Cura.cfg might contain secret data, so we don't back it up for now. IGNORED_FILES = {"cura.log"}
IGNORED_FILES = {"cura.log", "cura.cfg"}
def __init__(self, zip_file: bytes = None, meta_data: dict = None): def __init__(self, zip_file: bytes = None, meta_data: dict = None):
self.zip_file = zip_file # type: Optional[bytes] self.zip_file = zip_file # type: Optional[bytes]
@ -33,6 +34,9 @@ class Backup:
Logger.log("d", "Creating backup for Cura %s, using folder %s", cura_release, version_data_dir) Logger.log("d", "Creating backup for Cura %s, using folder %s", cura_release, version_data_dir)
# Ensure all current settings are saved.
CuraApplication.getInstance().saveSettings()
# We're using an easy to parse filename for when we're restoring edge cases: # We're using an easy to parse filename for when we're restoring edge cases:
# TIMESTAMP.backup.VERSION.cura.zip # TIMESTAMP.backup.VERSION.cura.zip
archive = self._makeArchive(version_data_dir) archive = self._makeArchive(version_data_dir)
@ -76,14 +80,31 @@ class Backup:
Logger.log("e", "Could not create archive from user data directory: %s", error) Logger.log("e", "Could not create archive from user data directory: %s", error)
return None return None
def restore(self) -> None: def restore(self) -> bool:
""" """
Restore this backup. Restore this backup.
""" """
if not self.zip_file or not self.meta_data or not self.meta_data.get("cura_release", None): if not self.zip_file or not self.meta_data or not self.meta_data.get("cura_release", None):
# We can restore without the minimum required information. # We can restore without the minimum required information.
Logger.log("w", "Tried to restore a Cura backup without having proper data or meta data.") Logger.log("w", "Tried to restore a Cura backup without having proper data or meta data.")
return return False
# global_data_dir = os.path.dirname(version_data_dir) # global_data_dir = os.path.dirname(version_data_dir)
# TODO: restore logic. # TODO: handle restoring older data version.
version_data_dir = Resources.getDataStoragePath()
archive = ZipFile(io.BytesIO(self.zip_file), "r")
extracted = self._extractArchive(archive, version_data_dir)
if not extracted:
return False
return True
@staticmethod
def _extractArchive(archive: "ZipFile", target_path: str) -> bool:
Logger.log("d", "Removing current data in location: %s", target_path)
shutil.rmtree(target_path)
Logger.log("d", "Extracting backup to location: %s", target_path)
archive.extractall(target_path)
return True

View File

@ -4,6 +4,7 @@ from typing import Optional
from UM.Logger import Logger from UM.Logger import Logger
from cura.Backups.Backup import Backup from cura.Backups.Backup import Backup
from cura.CuraApplication import CuraApplication
class BackupsManager: class BackupsManager:
@ -40,7 +41,11 @@ class BackupsManager:
self._disableAutoSave() self._disableAutoSave()
backup = Backup(zip_file = zip_file, meta_data = meta_data) backup = Backup(zip_file = zip_file, meta_data = meta_data)
backup.restore() # At this point, Cura will need to restart for the changes to take effect restored = backup.restore()
if restored:
# At this point, Cura will need to restart for the changes to take effect.
# We don't want to store the data at this point as that would override the just-restored backup.
CuraApplication.getInstance().windowClosed(safe_data=False)
def _disableAutoSave(self): def _disableAutoSave(self):
"""Here we try to disable the auto-save plugin as it might interfere with restoring a backup.""" """Here we try to disable the auto-save plugin as it might interfere with restoring a backup."""

View File

@ -497,10 +497,10 @@ class CuraApplication(QtApplication):
## Cura has multiple locations where instance containers need to be saved, so we need to handle this differently. ## Cura has multiple locations where instance containers need to be saved, so we need to handle this differently.
# #
# Note that the AutoSave plugin also calls this method. # Note that the AutoSave plugin also calls this method.
def saveSettings(self): def saveSettings(self, safe_data: bool = True):
if not self.started: # Do not do saving during application start if not self.started or not safe_data:
# Do not do saving during application start or when data should not be safed on quit.
return return
ContainerRegistry.getInstance().saveDirtyContainers() ContainerRegistry.getInstance().saveDirtyContainers()
def saveStack(self, stack): def saveStack(self, stack):

View File

@ -1025,6 +1025,25 @@
} }
} }
}, },
"UltimakerPC": {
"package_info": {
"package_id": "UltimakerPC",
"package_type": "material",
"display_name": "Ultimaker PC",
"description": "Example package for material and quality profiles for Ultimaker materials.",
"package_version": "1.0.0",
"cura_version": 4,
"website": "https://ultimaker.com/products/materials/pc",
"author": {
"author_id": "Ultimaker",
"display_name": "Ultimaker B.V.",
"email": "materials@ultimaker.com",
"website": "https://ultimaker.com",
"description": "Professional 3D printing made accessible.",
"support_website": "https://ultimaker.com/en/resources/troubleshooting/materials"
}
}
},
"UltimakerPLA": { "UltimakerPLA": {
"package_info": { "package_info": {
"package_id": "UltimakerPLA", "package_id": "UltimakerPLA",