Profile.py 8.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161
  1. # Copyright (c) 2016 Ultimaker B.V.
  2. # Cura is released under the terms of the AGPLv3 or higher.
  3. import configparser #To read config files.
  4. import io #To write config files to strings as if they were files.
  5. import UM.VersionUpgrade
  6. ## The materials in Cura 2.2.
  7. #
  8. # This is required to know how to split old profiles if the old machine didn't
  9. # have material-specific profiles but the new machine has. This cannot be read
  10. # from the current source directory since the current source directory may be
  11. # a later version than Cura 2.2, so it must be stored in the upgrade plug-in.
  12. _new_materials = {"generic_abs", "generic_cpe", "generic_pla", "generic_pva"}
  13. ## Creates a new profile instance by parsing a serialised profile in version 1
  14. # of the file format.
  15. #
  16. # \param serialised The serialised form of a profile in version 1.
  17. # \param filename The supposed filename of the profile, without extension.
  18. # \return A profile instance, or None if the file format is incorrect.
  19. def importFrom(serialised, filename):
  20. try:
  21. return Profile(serialised, filename)
  22. except (configparser.Error, UM.VersionUpgrade.FormatException, UM.VersionUpgrade.InvalidVersionException):
  23. return None
  24. ## A representation of a profile used as intermediary form for conversion from
  25. # one format to the other.
  26. class Profile:
  27. ## Reads version 1 of the file format, storing it in memory.
  28. #
  29. # \param serialised A string with the contents of a profile.
  30. # \param filename The supposed filename of the profile, without extension.
  31. def __init__(self, serialised, filename):
  32. self._filename = filename
  33. parser = configparser.ConfigParser(interpolation = None)
  34. parser.read_string(serialised)
  35. # Check correctness.
  36. if not parser.has_section("general"):
  37. raise UM.VersionUpgrade.FormatException("No \"general\" section.")
  38. if not parser.has_option("general", "version"):
  39. raise UM.VersionUpgrade.FormatException("No \"version\" in the \"general\" section.")
  40. if int(parser.get("general", "version")) != 1: # Hard-coded profile version here. If this number changes the entire function needs to change.
  41. raise UM.VersionUpgrade.InvalidVersionException("The version of this profile is wrong. It must be 1.")
  42. # Parse the general section.
  43. self._name = parser.get("general", "name")
  44. self._type = parser.get("general", "type", fallback = None)
  45. if "weight" in parser["general"]:
  46. self._weight = int(parser.get("general", "weight"))
  47. else:
  48. self._weight = None
  49. self._machine_type_id = parser.get("general", "machine_type", fallback = None)
  50. self._machine_variant_name = parser.get("general", "machine_variant", fallback = None)
  51. self._machine_instance_name = parser.get("general", "machine_instance", fallback = None)
  52. if "material" in parser["general"]:
  53. self._material_name = parser.get("general", "material")
  54. elif self._type == "material":
  55. self._material_name = parser.get("general", "name", fallback = None)
  56. else:
  57. self._material_name = None
  58. # Parse the settings.
  59. self._settings = {}
  60. if parser.has_section("settings"):
  61. for key, value in parser["settings"].items():
  62. self._settings[key] = value
  63. # Parse the defaults and the disabled defaults.
  64. self._changed_settings_defaults = {}
  65. if parser.has_section("defaults"):
  66. for key, value in parser["defaults"].items():
  67. self._changed_settings_defaults[key] = value
  68. self._disabled_settings_defaults = []
  69. if parser.has_section("disabled_defaults"):
  70. disabled_defaults_string = parser.get("disabled_defaults", "values")
  71. self._disabled_settings_defaults = [item for item in disabled_defaults_string.split(",") if item != ""] # Split by comma.
  72. ## Serialises this profile as file format version 2.
  73. #
  74. # \return A tuple containing the new filename and a serialised form of
  75. # this profile, serialised in version 2 of the file format.
  76. def export(self):
  77. import VersionUpgrade21to22 # Import here to prevent circular dependencies.
  78. if self._name == "Current settings":
  79. self._filename += "_current_settings" #This resolves a duplicate ID arising from how Cura 2.1 stores its current settings.
  80. config = configparser.ConfigParser(interpolation = None)
  81. config.add_section("general")
  82. config.set("general", "version", "2") #Hard-coded profile version 2.
  83. config.set("general", "name", self._name)
  84. if self._machine_type_id:
  85. translated_machine = VersionUpgrade21to22.VersionUpgrade21to22.VersionUpgrade21to22.translatePrinter(self._machine_type_id)
  86. config.set("general", "definition", translated_machine)
  87. else:
  88. config.set("general", "definition", "fdmprinter")
  89. config.add_section("metadata")
  90. if self._type:
  91. config.set("metadata", "type", self._type)
  92. else:
  93. config.set("metadata", "type", "quality")
  94. if self._weight:
  95. config.set("metadata", "weight", self._weight)
  96. if self._machine_variant_name:
  97. if self._machine_type_id:
  98. config.set("metadata", "variant", VersionUpgrade21to22.VersionUpgrade21to22.VersionUpgrade21to22.translateVariant(self._machine_variant_name, self._machine_type_id))
  99. else:
  100. config.set("metadata", "variant", self._machine_variant_name)
  101. if self._settings:
  102. VersionUpgrade21to22.VersionUpgrade21to22.VersionUpgrade21to22.translateSettings(self._settings)
  103. config.add_section("values")
  104. for key, value in self._settings.items():
  105. config.set("values", key, str(value))
  106. if self._changed_settings_defaults:
  107. VersionUpgrade21to22.VersionUpgrade21to22.VersionUpgrade21to22.translateSettings(self._changed_settings_defaults)
  108. config.add_section("defaults")
  109. for key, value in self._changed_settings_defaults.items():
  110. config.set("defaults", key, str(value))
  111. if self._disabled_settings_defaults:
  112. disabled_settings_defaults = [VersionUpgrade21to22.VersionUpgrade21to22.VersionUpgrade21to22.translateSettingName(setting)
  113. for setting in self._disabled_settings_defaults]
  114. config.add_section("disabled_defaults")
  115. disabled_defaults_string = str(disabled_settings_defaults[0]) #Must be at least 1 item, otherwise we wouldn't enter this if statement.
  116. for item in disabled_settings_defaults[1:]:
  117. disabled_defaults_string += "," + str(item)
  118. #Material metadata may cause the file to split, so do it last to minimise processing time (do more with the copy).
  119. filenames = []
  120. configs = []
  121. if self._material_name and self._type != "material":
  122. config.set("metadata", "material", self._material_name)
  123. filenames.append(self._filename)
  124. configs.append(config)
  125. elif self._type != "material" and self._machine_type_id in VersionUpgrade21to22.VersionUpgrade21to22.VersionUpgrade21to22.machinesWithMachineQuality():
  126. #Split this profile into multiple profiles, one for each material.
  127. for material_id in _new_materials:
  128. filenames.append("{profile}_{material}".format(profile = self._filename, material = material_id))
  129. config_copy = configparser.ConfigParser(interpolation = None)
  130. config_copy.read_dict(config) #Copy the config to a new ConfigParser instance.
  131. config_copy.set("metadata", "material", material_id)
  132. configs.append(config_copy)
  133. else:
  134. configs.append(config)
  135. filenames.append(self._filename)
  136. outputs = []
  137. for config in configs:
  138. output = io.StringIO()
  139. config.write(output)
  140. outputs.append(output.getvalue())
  141. return filenames, outputs