From 40d70b5f39373df41fd0fd49bc4d0fb6a4e7e52d Mon Sep 17 00:00:00 2001 From: Lipu Fei Date: Tue, 16 May 2017 14:37:12 +0200 Subject: [PATCH] Fix version upgrade for project loading CURA-3756 --- cura/CuraApplication.py | 9 ++++- cura/Settings/ContainerManager.py | 3 +- cura/Settings/CuraContainerRegistry.py | 4 +- cura/Settings/CuraStackBuilder.py | 6 +-- cura/Settings/ExtruderManager.py | 4 +- plugins/3MFReader/ThreeMFWorkspaceReader.py | 37 +++++++++++++++---- .../MachineSettingsAction.py | 4 +- .../UMOUpgradeSelection.py | 4 +- .../VersionUpgrade22to24/VersionUpgrade.py | 10 +++++ .../VersionUpgrade22to24/__init__.py | 6 +-- .../VersionUpgrade25to26.py | 15 ++++++-- .../VersionUpgrade25to26/__init__.py | 16 ++++---- 12 files changed, 84 insertions(+), 34 deletions(-) diff --git a/cura/CuraApplication.py b/cura/CuraApplication.py index 7e047cae0a..b85c1a2f54 100755 --- a/cura/CuraApplication.py +++ b/cura/CuraApplication.py @@ -99,6 +99,11 @@ if not MYPY: class CuraApplication(QtApplication): + # SettingVersion represents the set of settings available in the machine/extruder definitions. + # You need to make sure that this version number needs to be increased if there is any non-backwards-compatible + # changes of the settings. + SettingVersion = 1 + class ResourceTypes: QmlFiles = Resources.UserType + 1 Firmware = Resources.UserType + 2 @@ -169,11 +174,11 @@ class CuraApplication(QtApplication): UM.VersionUpgradeManager.VersionUpgradeManager.getInstance().setCurrentVersions( { - ("quality", InstanceContainer.Version): (self.ResourceTypes.QualityInstanceContainer, "application/x-uranium-instancecontainer"), + ("quality_changes", InstanceContainer.Version * 1000000 + self.SettingVersion): (self.ResourceTypes.QualityInstanceContainer, "application/x-uranium-instancecontainer"), ("machine_stack", ContainerStack.Version): (self.ResourceTypes.MachineStack, "application/x-uranium-containerstack"), ("extruder_train", ContainerStack.Version): (self.ResourceTypes.ExtruderStack, "application/x-uranium-extruderstack"), ("preferences", Preferences.Version): (Resources.Preferences, "application/x-uranium-preferences"), - ("user", InstanceContainer.Version): (self.ResourceTypes.UserInstanceContainer, "application/x-uranium-instancecontainer") + ("user", InstanceContainer.Version * 1000000 + self.SettingVersion): (self.ResourceTypes.UserInstanceContainer, "application/x-uranium-instancecontainer") } ) diff --git a/cura/Settings/ContainerManager.py b/cura/Settings/ContainerManager.py index dee468f069..ff7b2d8020 100644 --- a/cura/Settings/ContainerManager.py +++ b/cura/Settings/ContainerManager.py @@ -28,6 +28,7 @@ from UM.Settings.ContainerRegistry import ContainerRegistry from UM.i18n import i18nCatalog +import cura.CuraApplication from cura.Settings.ExtruderManager import ExtruderManager catalog = i18nCatalog("cura") @@ -918,7 +919,7 @@ class ContainerManager(QObject): quality_changes.setDefinition(self._container_registry.findContainers(id = "fdmprinter")[0]) else: quality_changes.setDefinition(QualityManager.getInstance().getParentMachineDefinition(machine_definition)) - quality_changes.addMetaDataEntry("setting_version", quality_changes.getDefinition().getMetaDataEntry("setting_version", default = 0)) + quality_changes.addMetaDataEntry("setting_version", cura.CuraApplication.CuraApplication.SettingVersion) return quality_changes diff --git a/cura/Settings/CuraContainerRegistry.py b/cura/Settings/CuraContainerRegistry.py index 2943ed009d..7961e8db31 100644 --- a/cura/Settings/CuraContainerRegistry.py +++ b/cura/Settings/CuraContainerRegistry.py @@ -22,6 +22,8 @@ from . import GlobalStack from .ContainerManager import ContainerManager from .ExtruderManager import ExtruderManager +from cura.CuraApplication import CuraApplication + from UM.i18n import i18nCatalog catalog = i18nCatalog("cura") @@ -43,7 +45,7 @@ class CuraContainerRegistry(ContainerRegistry): if isinstance(container, InstanceContainer) and type(container) != type(self.getEmptyInstanceContainer()): #Check against setting version of the definition. - required_setting_version = int(container.getDefinition().getMetaDataEntry("setting_version", default = 0)) + required_setting_version = CuraApplication.SettingVersion actual_setting_version = int(container.getMetaDataEntry("setting_version", default = 0)) if required_setting_version != actual_setting_version: Logger.log("w", "Instance container {container_id} is outdated. Its setting version is {actual_setting_version} but it should be {required_setting_version}.".format(container_id = container.getId(), actual_setting_version = actual_setting_version, required_setting_version = required_setting_version)) diff --git a/cura/Settings/CuraStackBuilder.py b/cura/Settings/CuraStackBuilder.py index 652425ba6a..17b461e2d2 100644 --- a/cura/Settings/CuraStackBuilder.py +++ b/cura/Settings/CuraStackBuilder.py @@ -9,9 +9,9 @@ from UM.Settings.ContainerRegistry import ContainerRegistry from .GlobalStack import GlobalStack from .ExtruderStack import ExtruderStack -from .CuraContainerStack import CuraContainerStack from typing import Optional +import cura.CuraApplication ## Contains helper functions to create new machines. class CuraStackBuilder: @@ -76,7 +76,7 @@ class CuraStackBuilder: user_container = InstanceContainer(new_stack_id + "_user") user_container.addMetaDataEntry("type", "user") user_container.addMetaDataEntry("extruder", new_stack_id) - user_container.addMetaDataEntry("setting_version", machine_definition.getMetaDataEntry("setting_version", default = 0)) + user_container.addMetaDataEntry("setting_version", cura.CuraApplication.CuraApplication.SettingVersion) user_container.setDefinition(machine_definition) stack.setUserChanges(user_container) @@ -125,7 +125,7 @@ class CuraStackBuilder: user_container = InstanceContainer(new_stack_id + "_user") user_container.addMetaDataEntry("type", "user") user_container.addMetaDataEntry("machine", new_stack_id) - user_container.addMetaDataEntry("setting_version", definition.getMetaDataEntry("setting_version", default = 0)) + user_container.addMetaDataEntry("setting_version", cura.CuraApplication.CuraApplication.SettingVersion) user_container.setDefinition(definition) stack.setUserChanges(user_container) diff --git a/cura/Settings/ExtruderManager.py b/cura/Settings/ExtruderManager.py index 40d8fe7a19..9e1e65c911 100755 --- a/cura/Settings/ExtruderManager.py +++ b/cura/Settings/ExtruderManager.py @@ -18,6 +18,8 @@ from UM.Settings.ContainerStack import ContainerStack from UM.Settings.DefinitionContainer import DefinitionContainer from typing import Optional, List, TYPE_CHECKING, Union +import cura.CuraApplication + if TYPE_CHECKING: from cura.Settings.ExtruderStack import ExtruderStack from cura.Settings.GlobalStack import GlobalStack @@ -363,7 +365,7 @@ class ExtruderManager(QObject): user_profile = InstanceContainer(extruder_stack_id + "_current_settings") # Add an empty user profile. user_profile.addMetaDataEntry("type", "user") user_profile.addMetaDataEntry("extruder", extruder_stack_id) - user_profile.addMetaDataEntry("setting_version", machine_definition.getMetaDataEntry("setting_version", default = 0)) + user_profile.addMetaDataEntry("setting_version", cura.CuraApplication.CuraApplication.SettingVersion) user_profile.setDefinition(machine_definition) container_registry.addContainer(user_profile) container_stack.addContainer(user_profile) diff --git a/plugins/3MFReader/ThreeMFWorkspaceReader.py b/plugins/3MFReader/ThreeMFWorkspaceReader.py index e1b65805c1..593591b5dc 100755 --- a/plugins/3MFReader/ThreeMFWorkspaceReader.py +++ b/plugins/3MFReader/ThreeMFWorkspaceReader.py @@ -46,6 +46,12 @@ class ThreeMFWorkspaceReader(WorkspaceReader): self._extruder_stack_suffix = "." + ContainerRegistry.getMimeTypeForContainer(ExtruderStack).preferredSuffix self._global_stack_suffix = "." + ContainerRegistry.getMimeTypeForContainer(GlobalStack).preferredSuffix + # Certain instance container types are ignored because we make the assumption that only we make those types + # of containers. They are: + # - quality + # - variant + self._ignored_instance_container_types = {"quality", "variant"} + self._resolve_strategies = {} self._id_mapping = {} @@ -183,6 +189,7 @@ class ThreeMFWorkspaceReader(WorkspaceReader): num_user_settings = 0 quality_changes_conflict = False definition_changes_conflict = False + for each_instance_container_file in instance_container_files: container_id = self._stripFileToId(each_instance_container_file) instance_container = InstanceContainer(container_id) @@ -208,14 +215,12 @@ class ThreeMFWorkspaceReader(WorkspaceReader): if definition_changes: if definition_changes[0] != instance_container: definition_changes_conflict = True - elif container_type == "quality": - # If the quality name is not set (either by quality or changes, set it now) - # Quality changes should always override this (as they are "on top") - if quality_name == "": - quality_name = instance_container.getName() - quality_type = instance_container.getName() elif container_type == "user": num_user_settings += len(instance_container._instances) + elif container_type in self._ignored_instance_container_types: + # Ignore certain instance container types + Logger.log("w", "Ignoring instance container [%s] with type [%s]", container_id, container_type) + continue Job.yieldThread() @@ -417,13 +422,29 @@ class ThreeMFWorkspaceReader(WorkspaceReader): quality_and_definition_changes_instance_containers = [] for instance_container_file in instance_container_files: container_id = self._stripFileToId(instance_container_file) + serialized = archive.open(instance_container_file).read().decode("utf-8") + + # HACK! we ignore the "metadata/type = quality" instance containers! + parser = configparser.ConfigParser() + parser.read_string(serialized) + if not parser.has_option("metadata", "type"): + Logger.log("w", "Cannot find metadata/type in %s, ignoring it", instance_container_file) + continue + if parser.get("metadata", "type") == "quality": + continue + instance_container = InstanceContainer(container_id) # Deserialize InstanceContainer by converting read data from bytes to string - instance_container.deserialize(archive.open(instance_container_file).read().decode("utf-8")) + instance_container.deserialize(serialized) container_type = instance_container.getMetaDataEntry("type") Job.yieldThread() - if container_type == "user": + + if container_type in self._ignored_instance_container_types: + # Ignore certain instance container types + Logger.log("w", "Ignoring instance container [%s] with type [%s]", container_id, container_type) + continue + elif container_type == "user": # Check if quality changes already exists. user_containers = self._container_registry.findInstanceContainers(id = container_id) if not user_containers: diff --git a/plugins/MachineSettingsAction/MachineSettingsAction.py b/plugins/MachineSettingsAction/MachineSettingsAction.py index f09d1f2b1d..983b70d174 100755 --- a/plugins/MachineSettingsAction/MachineSettingsAction.py +++ b/plugins/MachineSettingsAction/MachineSettingsAction.py @@ -14,7 +14,7 @@ from UM.Settings.DefinitionContainer import DefinitionContainer from UM.Scene.Iterator.DepthFirstIterator import DepthFirstIterator from UM.Logger import Logger -from cura.Settings.CuraContainerRegistry import CuraContainerRegistry +from cura.CuraApplication import CuraApplication from cura.Settings.ExtruderManager import ExtruderManager import UM.i18n @@ -99,7 +99,7 @@ class MachineSettingsAction(MachineAction): definition = container_stack.getBottom() definition_changes_container.setDefinition(definition) definition_changes_container.addMetaDataEntry("type", "definition_changes") - definition_changes_container.addMetaDataEntry("setting_version", definition.getMetaDataEntry("setting_version", default = 0)) + definition_changes_container.addMetaDataEntry("setting_version", CuraApplication.SettingVersion) self._container_registry.addContainer(definition_changes_container) container_stack.definitionChanges = definition_changes_container diff --git a/plugins/UltimakerMachineActions/UMOUpgradeSelection.py b/plugins/UltimakerMachineActions/UMOUpgradeSelection.py index d2c3b31359..02b1482719 100644 --- a/plugins/UltimakerMachineActions/UMOUpgradeSelection.py +++ b/plugins/UltimakerMachineActions/UMOUpgradeSelection.py @@ -11,7 +11,7 @@ from UM.Application import Application catalog = i18nCatalog("cura") import UM.Settings.InstanceContainer - +from cura.CuraApplication import CuraApplication ## The Ultimaker Original can have a few revisions & upgrades. This action helps with selecting them, so they are added # as a variant. @@ -49,7 +49,7 @@ class UMOUpgradeSelection(MachineAction): definition = global_container_stack.getBottom() definition_changes_container.setDefinition(definition) definition_changes_container.addMetaDataEntry("type", "definition_changes") - definition_changes_container.addMetaDataEntry("setting_version", definition.getMetaDataEntry("setting_version", default = 0)) + definition_changes_container.addMetaDataEntry("setting_version", CuraApplication.SettingVersion) UM.Settings.ContainerRegistry.ContainerRegistry.getInstance().addContainer(definition_changes_container) # Insert definition_changes between the definition and the variant diff --git a/plugins/VersionUpgrade/VersionUpgrade22to24/VersionUpgrade.py b/plugins/VersionUpgrade/VersionUpgrade22to24/VersionUpgrade.py index ab934210f6..9d508e553b 100644 --- a/plugins/VersionUpgrade/VersionUpgrade22to24/VersionUpgrade.py +++ b/plugins/VersionUpgrade/VersionUpgrade22to24/VersionUpgrade.py @@ -142,6 +142,16 @@ class VersionUpgrade22to24(VersionUpgrade): config.write(output) return [filename], [output.getvalue()] + def upgradeQuality(self, serialised, filename): + config = configparser.ConfigParser(interpolation = None) + config.read_string(serialised) # Read the input string as config file. + config.set("metadata", "type", "quality_changes") # Update metadata/type to quality_changes + config.set("general", "version", "2") # Just bump the version number. That is all we need for now. + + output = io.StringIO() + config.write(output) + return [filename], [output.getvalue()] + def getCfgVersion(self, serialised): parser = configparser.ConfigParser(interpolation = None) parser.read_string(serialised) diff --git a/plugins/VersionUpgrade/VersionUpgrade22to24/__init__.py b/plugins/VersionUpgrade/VersionUpgrade22to24/__init__.py index 0df2c94b75..0ff121f35e 100644 --- a/plugins/VersionUpgrade/VersionUpgrade22to24/__init__.py +++ b/plugins/VersionUpgrade/VersionUpgrade22to24/__init__.py @@ -21,9 +21,9 @@ def getMetaData(): # From To Upgrade function ("machine_instance", 2000000): ("machine_stack", 3000000, upgrade.upgradeMachineInstance), ("extruder_train", 2000000): ("extruder_train", 3000000, upgrade.upgradeExtruderTrain), - ("preferences", 3000000): ("preferences", 4000000, upgrade.upgradePreferences) - - }, + ("preferences", 3000000): ("preferences", 4000000, upgrade.upgradePreferences), + ("quality", 2000000): ("quality_changes", 2000000, upgrade.upgradeQuality), + }, "sources": { "machine_stack": { "get_version": upgrade.getCfgVersion, diff --git a/plugins/VersionUpgrade/VersionUpgrade25to26/VersionUpgrade25to26.py b/plugins/VersionUpgrade/VersionUpgrade25to26/VersionUpgrade25to26.py index c61962d276..85f54dd654 100644 --- a/plugins/VersionUpgrade/VersionUpgrade25to26/VersionUpgrade25to26.py +++ b/plugins/VersionUpgrade/VersionUpgrade25to26/VersionUpgrade25to26.py @@ -5,6 +5,7 @@ import configparser #To parse the files we need to upgrade and write the new fil import io #To serialise configparser output to a string. from UM.VersionUpgrade import VersionUpgrade +from cura.CuraApplication import CuraApplication _removed_settings = { #Settings that were removed in 2.5. "start_layers_at_same_position", @@ -86,11 +87,17 @@ class VersionUpgrade25to26(VersionUpgrade): parser["values"][replacement] = parser["values"][replaced_setting] #Copy to replacement before removing the original! del replaced_setting - #Change the version number in the file. - if parser.has_section("general"): - parser["general"]["setting_version"] = "1" + for each_section in ("general", "metadata"): + if not parser.has_section(each_section): + parser.add_section(each_section) + + # Change the version number in the file. + parser["metadata"]["setting_version"] = str(CuraApplication.SettingVersion) + + # Update version + parser["general"]["version"] = "2" #Re-serialise the file. output = io.StringIO() parser.write(output) - return [filename], [output.getvalue()] \ No newline at end of file + return [filename], [output.getvalue()] diff --git a/plugins/VersionUpgrade/VersionUpgrade25to26/__init__.py b/plugins/VersionUpgrade/VersionUpgrade25to26/__init__.py index 3aee161e3c..a24473f65d 100644 --- a/plugins/VersionUpgrade/VersionUpgrade25to26/__init__.py +++ b/plugins/VersionUpgrade/VersionUpgrade25to26/__init__.py @@ -18,14 +18,16 @@ def getMetaData(): "api": 3 }, "version_upgrade": { - # From To Upgrade function - ("preferences", 4000000): ("preferences", 4000001, upgrade.upgradePreferences), - ("quality", 2000000): ("quality", 2000001, upgrade.upgradeInstanceContainer), - ("variant", 2000000): ("variant", 2000001, upgrade.upgradeInstanceContainer), #We can re-use upgradeContainerStack since there is nothing specific to quality, variant or user profiles being changed. - ("user", 2000000): ("user", 2000001, upgrade.upgradeInstanceContainer) + # From To Upgrade function + ("preferences", 4000000): ("preferences", 4000001, upgrade.upgradePreferences), + # NOTE: All the instance containers share the same general/version, so we have to update all of them + # if any is updated. + ("quality_changes", 2000000): ("quality_changes", 2000001, upgrade.upgradeInstanceContainer), + ("user", 2000000): ("user", 2000001, upgrade.upgradeInstanceContainer), + ("quality", 2000000): ("quality", 2000001, upgrade.upgradeInstanceContainer), }, "sources": { - "quality": { + "quality_changes": { "get_version": upgrade.getCfgVersion, "location": {"./quality"} }, @@ -36,7 +38,7 @@ def getMetaData(): "user": { "get_version": upgrade.getCfgVersion, "location": {"./user"} - } + }, } }