Fix version upgrade for project loading

CURA-3756
This commit is contained in:
Lipu Fei 2017-05-16 14:37:12 +02:00
parent 1b4564bdb1
commit 40d70b5f39
12 changed files with 84 additions and 34 deletions

View file

@ -99,6 +99,11 @@ if not MYPY:
class CuraApplication(QtApplication): 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: class ResourceTypes:
QmlFiles = Resources.UserType + 1 QmlFiles = Resources.UserType + 1
Firmware = Resources.UserType + 2 Firmware = Resources.UserType + 2
@ -169,11 +174,11 @@ class CuraApplication(QtApplication):
UM.VersionUpgradeManager.VersionUpgradeManager.getInstance().setCurrentVersions( 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"), ("machine_stack", ContainerStack.Version): (self.ResourceTypes.MachineStack, "application/x-uranium-containerstack"),
("extruder_train", ContainerStack.Version): (self.ResourceTypes.ExtruderStack, "application/x-uranium-extruderstack"), ("extruder_train", ContainerStack.Version): (self.ResourceTypes.ExtruderStack, "application/x-uranium-extruderstack"),
("preferences", Preferences.Version): (Resources.Preferences, "application/x-uranium-preferences"), ("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")
} }
) )

View file

@ -28,6 +28,7 @@ from UM.Settings.ContainerRegistry import ContainerRegistry
from UM.i18n import i18nCatalog from UM.i18n import i18nCatalog
import cura.CuraApplication
from cura.Settings.ExtruderManager import ExtruderManager from cura.Settings.ExtruderManager import ExtruderManager
catalog = i18nCatalog("cura") catalog = i18nCatalog("cura")
@ -918,7 +919,7 @@ class ContainerManager(QObject):
quality_changes.setDefinition(self._container_registry.findContainers(id = "fdmprinter")[0]) quality_changes.setDefinition(self._container_registry.findContainers(id = "fdmprinter")[0])
else: else:
quality_changes.setDefinition(QualityManager.getInstance().getParentMachineDefinition(machine_definition)) 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 return quality_changes

View file

@ -22,6 +22,8 @@ from . import GlobalStack
from .ContainerManager import ContainerManager from .ContainerManager import ContainerManager
from .ExtruderManager import ExtruderManager from .ExtruderManager import ExtruderManager
from cura.CuraApplication import CuraApplication
from UM.i18n import i18nCatalog from UM.i18n import i18nCatalog
catalog = i18nCatalog("cura") catalog = i18nCatalog("cura")
@ -43,7 +45,7 @@ class CuraContainerRegistry(ContainerRegistry):
if isinstance(container, InstanceContainer) and type(container) != type(self.getEmptyInstanceContainer()): if isinstance(container, InstanceContainer) and type(container) != type(self.getEmptyInstanceContainer()):
#Check against setting version of the definition. #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)) actual_setting_version = int(container.getMetaDataEntry("setting_version", default = 0))
if required_setting_version != actual_setting_version: 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)) 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))

View file

@ -9,9 +9,9 @@ from UM.Settings.ContainerRegistry import ContainerRegistry
from .GlobalStack import GlobalStack from .GlobalStack import GlobalStack
from .ExtruderStack import ExtruderStack from .ExtruderStack import ExtruderStack
from .CuraContainerStack import CuraContainerStack
from typing import Optional from typing import Optional
import cura.CuraApplication
## Contains helper functions to create new machines. ## Contains helper functions to create new machines.
class CuraStackBuilder: class CuraStackBuilder:
@ -76,7 +76,7 @@ class CuraStackBuilder:
user_container = InstanceContainer(new_stack_id + "_user") user_container = InstanceContainer(new_stack_id + "_user")
user_container.addMetaDataEntry("type", "user") user_container.addMetaDataEntry("type", "user")
user_container.addMetaDataEntry("extruder", new_stack_id) 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) user_container.setDefinition(machine_definition)
stack.setUserChanges(user_container) stack.setUserChanges(user_container)
@ -125,7 +125,7 @@ class CuraStackBuilder:
user_container = InstanceContainer(new_stack_id + "_user") user_container = InstanceContainer(new_stack_id + "_user")
user_container.addMetaDataEntry("type", "user") user_container.addMetaDataEntry("type", "user")
user_container.addMetaDataEntry("machine", new_stack_id) 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) user_container.setDefinition(definition)
stack.setUserChanges(user_container) stack.setUserChanges(user_container)

View file

@ -18,6 +18,8 @@ from UM.Settings.ContainerStack import ContainerStack
from UM.Settings.DefinitionContainer import DefinitionContainer from UM.Settings.DefinitionContainer import DefinitionContainer
from typing import Optional, List, TYPE_CHECKING, Union from typing import Optional, List, TYPE_CHECKING, Union
import cura.CuraApplication
if TYPE_CHECKING: if TYPE_CHECKING:
from cura.Settings.ExtruderStack import ExtruderStack from cura.Settings.ExtruderStack import ExtruderStack
from cura.Settings.GlobalStack import GlobalStack 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 = InstanceContainer(extruder_stack_id + "_current_settings") # Add an empty user profile.
user_profile.addMetaDataEntry("type", "user") user_profile.addMetaDataEntry("type", "user")
user_profile.addMetaDataEntry("extruder", extruder_stack_id) 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) user_profile.setDefinition(machine_definition)
container_registry.addContainer(user_profile) container_registry.addContainer(user_profile)
container_stack.addContainer(user_profile) container_stack.addContainer(user_profile)

View file

@ -46,6 +46,12 @@ class ThreeMFWorkspaceReader(WorkspaceReader):
self._extruder_stack_suffix = "." + ContainerRegistry.getMimeTypeForContainer(ExtruderStack).preferredSuffix self._extruder_stack_suffix = "." + ContainerRegistry.getMimeTypeForContainer(ExtruderStack).preferredSuffix
self._global_stack_suffix = "." + ContainerRegistry.getMimeTypeForContainer(GlobalStack).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._resolve_strategies = {}
self._id_mapping = {} self._id_mapping = {}
@ -183,6 +189,7 @@ class ThreeMFWorkspaceReader(WorkspaceReader):
num_user_settings = 0 num_user_settings = 0
quality_changes_conflict = False quality_changes_conflict = False
definition_changes_conflict = False definition_changes_conflict = False
for each_instance_container_file in instance_container_files: for each_instance_container_file in instance_container_files:
container_id = self._stripFileToId(each_instance_container_file) container_id = self._stripFileToId(each_instance_container_file)
instance_container = InstanceContainer(container_id) instance_container = InstanceContainer(container_id)
@ -208,14 +215,12 @@ class ThreeMFWorkspaceReader(WorkspaceReader):
if definition_changes: if definition_changes:
if definition_changes[0] != instance_container: if definition_changes[0] != instance_container:
definition_changes_conflict = True 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": elif container_type == "user":
num_user_settings += len(instance_container._instances) 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() Job.yieldThread()
@ -417,13 +422,29 @@ class ThreeMFWorkspaceReader(WorkspaceReader):
quality_and_definition_changes_instance_containers = [] quality_and_definition_changes_instance_containers = []
for instance_container_file in instance_container_files: for instance_container_file in instance_container_files:
container_id = self._stripFileToId(instance_container_file) 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) instance_container = InstanceContainer(container_id)
# Deserialize InstanceContainer by converting read data from bytes to string # 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") container_type = instance_container.getMetaDataEntry("type")
Job.yieldThread() 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. # Check if quality changes already exists.
user_containers = self._container_registry.findInstanceContainers(id = container_id) user_containers = self._container_registry.findInstanceContainers(id = container_id)
if not user_containers: if not user_containers:

View file

@ -14,7 +14,7 @@ from UM.Settings.DefinitionContainer import DefinitionContainer
from UM.Scene.Iterator.DepthFirstIterator import DepthFirstIterator from UM.Scene.Iterator.DepthFirstIterator import DepthFirstIterator
from UM.Logger import Logger from UM.Logger import Logger
from cura.Settings.CuraContainerRegistry import CuraContainerRegistry from cura.CuraApplication import CuraApplication
from cura.Settings.ExtruderManager import ExtruderManager from cura.Settings.ExtruderManager import ExtruderManager
import UM.i18n import UM.i18n
@ -99,7 +99,7 @@ class MachineSettingsAction(MachineAction):
definition = container_stack.getBottom() definition = container_stack.getBottom()
definition_changes_container.setDefinition(definition) definition_changes_container.setDefinition(definition)
definition_changes_container.addMetaDataEntry("type", "definition_changes") 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) self._container_registry.addContainer(definition_changes_container)
container_stack.definitionChanges = definition_changes_container container_stack.definitionChanges = definition_changes_container

View file

@ -11,7 +11,7 @@ from UM.Application import Application
catalog = i18nCatalog("cura") catalog = i18nCatalog("cura")
import UM.Settings.InstanceContainer 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 ## The Ultimaker Original can have a few revisions & upgrades. This action helps with selecting them, so they are added
# as a variant. # as a variant.
@ -49,7 +49,7 @@ class UMOUpgradeSelection(MachineAction):
definition = global_container_stack.getBottom() definition = global_container_stack.getBottom()
definition_changes_container.setDefinition(definition) definition_changes_container.setDefinition(definition)
definition_changes_container.addMetaDataEntry("type", "definition_changes") 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) UM.Settings.ContainerRegistry.ContainerRegistry.getInstance().addContainer(definition_changes_container)
# Insert definition_changes between the definition and the variant # Insert definition_changes between the definition and the variant

View file

@ -142,6 +142,16 @@ class VersionUpgrade22to24(VersionUpgrade):
config.write(output) config.write(output)
return [filename], [output.getvalue()] 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): def getCfgVersion(self, serialised):
parser = configparser.ConfigParser(interpolation = None) parser = configparser.ConfigParser(interpolation = None)
parser.read_string(serialised) parser.read_string(serialised)

View file

@ -21,9 +21,9 @@ def getMetaData():
# From To Upgrade function # From To Upgrade function
("machine_instance", 2000000): ("machine_stack", 3000000, upgrade.upgradeMachineInstance), ("machine_instance", 2000000): ("machine_stack", 3000000, upgrade.upgradeMachineInstance),
("extruder_train", 2000000): ("extruder_train", 3000000, upgrade.upgradeExtruderTrain), ("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": { "sources": {
"machine_stack": { "machine_stack": {
"get_version": upgrade.getCfgVersion, "get_version": upgrade.getCfgVersion,

View file

@ -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. import io #To serialise configparser output to a string.
from UM.VersionUpgrade import VersionUpgrade from UM.VersionUpgrade import VersionUpgrade
from cura.CuraApplication import CuraApplication
_removed_settings = { #Settings that were removed in 2.5. _removed_settings = { #Settings that were removed in 2.5.
"start_layers_at_same_position", "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! parser["values"][replacement] = parser["values"][replaced_setting] #Copy to replacement before removing the original!
del replaced_setting del replaced_setting
#Change the version number in the file. for each_section in ("general", "metadata"):
if parser.has_section("general"): if not parser.has_section(each_section):
parser["general"]["setting_version"] = "1" 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. #Re-serialise the file.
output = io.StringIO() output = io.StringIO()
parser.write(output) parser.write(output)
return [filename], [output.getvalue()] return [filename], [output.getvalue()]

View file

@ -18,14 +18,16 @@ def getMetaData():
"api": 3 "api": 3
}, },
"version_upgrade": { "version_upgrade": {
# From To Upgrade function # From To Upgrade function
("preferences", 4000000): ("preferences", 4000001, upgrade.upgradePreferences), ("preferences", 4000000): ("preferences", 4000001, upgrade.upgradePreferences),
("quality", 2000000): ("quality", 2000001, upgrade.upgradeInstanceContainer), # NOTE: All the instance containers share the same general/version, so we have to update all of them
("variant", 2000000): ("variant", 2000001, upgrade.upgradeInstanceContainer), #We can re-use upgradeContainerStack since there is nothing specific to quality, variant or user profiles being changed. # if any is updated.
("user", 2000000): ("user", 2000001, upgrade.upgradeInstanceContainer) ("quality_changes", 2000000): ("quality_changes", 2000001, upgrade.upgradeInstanceContainer),
("user", 2000000): ("user", 2000001, upgrade.upgradeInstanceContainer),
("quality", 2000000): ("quality", 2000001, upgrade.upgradeInstanceContainer),
}, },
"sources": { "sources": {
"quality": { "quality_changes": {
"get_version": upgrade.getCfgVersion, "get_version": upgrade.getCfgVersion,
"location": {"./quality"} "location": {"./quality"}
}, },
@ -36,7 +38,7 @@ def getMetaData():
"user": { "user": {
"get_version": upgrade.getCfgVersion, "get_version": upgrade.getCfgVersion,
"location": {"./user"} "location": {"./user"}
} },
} }
} }