Profile.py 8.7 KB

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